温习设计模式

OO基础:

  • 抽象
  • 封装
  • 多态
  • 继承

 

OO设计特性:

  • 可复用
  • 可扩充
  • 可维护


设计原则:

  • 封装变化:把会变化的部分取出并“封装”起来,好让其他部分不会受到影响(找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起)
  • 针对接口编程,而不是针对实现编程
  • 多用组合,少用继承
  • 为了交互对象之间的松耦合设计而努力
  • 类应该对扩展开放,对修改封闭

 

设计模式:

  • 策略模式:定义了算法族,分别封装起来,让他们之前可以互相替换,此模式让算法的变化独立于使用算法的客户
  • 观察者模式:定义了对象之前的一对多依赖,这样一来,对一个对象改变状态时,它的所有依赖者都会收到通知并自动更新(java也内置了观察者模式:参考java.util.Observer观察者接口、被观察者java.util.Observable接口)
  • 装饰者模式:动态的将责任附加到对象上,若有扩展功能,装饰者提供了比继承更有弹性的替代方案(前提:装饰者和被装饰对象有相同的超类型)、(java中的io大量使用装饰者模式:)
  • 简单工厂模式:简单工厂其实不是一个设计模式,反而更像一种编程习惯,定义一个生产工厂类,根据输入类型生产对应的产品(利用静态方法根据输入参数生成对应的产品,隐藏了产品实例化的细节),但是当用户需要新增产品ProductD时,必须在工厂类的生产方法中增加对应的判断分支,所以简单工厂模式违背了开放封闭原则
  • 工厂模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类;符合开放封闭原则,但是由于每增加一个产品,都需要新增对应的生产工厂,导致增加额外的开发工作量
  • 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
  • 单例模式:一个类只有一个实例,并提供一个全局访问点
  • 适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间

难理解的模式下面给了示例,读者根据示例更容易理解一点

 

代码示例:

简单工厂模式:

简单工厂模式:
首先定义一个产品类的共同接口:
public interface Product{
  //价格
  int price();
  //产品名
  String getName();
}
分别有三个产品ProductA、ProductB、ProductC ,均实现Product接口:
public class ProductA implements Product {
    @Override
    public int price() {
        return 100;
    }

    @Override
    public String getName() {
        return "ProductA";
    }
}
public class ProductB implements Product {
    @Override
    public int price() {
        return 200;
    }

    @Override
    public String getName() {
        return "ProductB";
    }
}
public class ProductC implements Product {
    @Override
    public int price() {
        return 300;
    }

    @Override
    public String getName() {
        return "ProductC";
    }
}
定义一个生产工厂类,根据输入类型生产对应的产品:
public class Factory {
    public static Product createProduct(String type){
        Product product =null;
        switch (type){
            case "A":
                product = new ProductA();
                break;
            case "B":
                product = new ProductB();
                break;
            case "C":
                product = new ProductC();
                break;
        }
        return product;
    }
}

工厂模式:

首先声明一个工厂接口,所有工厂必须实现这个接口:
public interface IFactory {
    Product createProduct();
}
生产ProductA的工厂FactoryA:
public class FactoryA implements IFactory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}
生产ProductB的工厂FactoryB:
public class FactoryB implements IFactory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}
现在来根据新的工厂方法模式来生产:
IFactory factoryA = new FactoryA();
Product productA = factoryA.createProduct();

IFactory factoryB = new FactoryB();
Product productB = factoryB.createProduct();

抽象工厂模式:

假设现在需要针对每种产品生产对应的赠品,难道我们要新增一个Gift的生产工厂吗?其实没有必要,因为在这个场景下,每种产品必须附带了赠品,所以我们可以利用原有的工厂来生产赠品
先定一个共同的Gift接口:
public interface Gift {
    String getGiftName();
}
增加GiftA、GiftB:
public class GiftA implements Gift {
    @Override
    public String getGiftName() {
        return "GiftA";
    }
}
修改Factory接口,增加生产Gift的方法:
public interface IFactory { 
    Product createProduct();
    Gift createGift();
}
修改工厂方法模式下的FactoryA、FactoryB、FactoryC:
public class FactoryA implements IFactory {
    @Override
    public Gift createGift() {
        return new GiftA();
    }
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}
生产产品和赠品:
IFactory factoryA = new FactoryA();
Product productA = factoryA.createProduct();
Gift giftA = factoryA.createGift();

装饰者模式:

以点餐为例,我在麦*劳点餐可以根据我需求增加食物种类和数量
抽象构件角色:
public interface Food {
    String getDescription();
}
具体构件角色:
public class BasicSet implements Food{
    @Override
    public String getDescription() {
        return "汉堡 + 可乐";
    }
}
抽象装饰类角色:
public abstract class Decorator implements Food {

    private Food food;

    public Decorator(Food food) {
        this.food = food;
    }

    @Override
    public String getDescription() {
        return this.food.getDescription();
    }
}
具体装饰类角色:
public class FrenchFries extends Decorator {
    public FrenchFries(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 薯条";
    }
}
public class FriedChicken extends Decorator {
    public FriedChicken(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 炸鸡";
    }
}
public class IceCream extends Decorator {
    public IceCream(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 冰淇淋";
    }
}
测试类:
public class Test {
    public static void main(String[] args) {
        Food food = new BasicSet();
        Decorator setMealA = new FrenchFries(food);
        setMealA = new FrenchFries(setMealA);
        setMealA = new FriedChicken(setMealA);
        setMealA = new IceCream(setMealA);
        System.out.println("套餐A:" + setMealA.getDescription());
    }
}
输出结果:
套餐A:汉堡 + 可乐 + 薯条 + 薯条 + 炸鸡 + 冰淇淋

单例模式:

第一种(懒汉,线程不安全):这种写法lazy loading很明显,但是致命的是在多线程不能正常工作
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

第二种(懒汉,线程安全):这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

第三种(饿汉):
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
       return instance;  
    }  
}  

第四种(饿汉,变种):
public class Singleton {  
    private Singleton instance = null;  
    static {  
       instance = new Singleton();  
    }  
    private Singleton (){}  
    public static Singleton getInstance() {  
       return this.instance;  
    }  
}  

第五种(静态内部类):
public class Singleton {  
    private static class SingletonHolder {  
      private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
       return SingletonHolder.INSTANCE;  
    }  
} 
这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理


第六种(双重校验锁):
public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
          if (singleton == null) {  
            singleton = new Singleton();  
          }  
        }  
    }  
    return singleton;  
    }  
}  
为什么要加volatile关键字来修饰singleton对象?因为new Singleton()这块存在重排序的问题,可能导致单例非单例,加上volatile后能让jvm限制指令重排序,这样就没有问题了

适配器模式:

目标角色(PowerTarget.java):
public interface PowerTarget {
    public int output5V();
}

适配者角色(PowerAdaptee.java):
public class PowerAdaptee {
    private int output =  220;
    public int output220V() {
        System.out.println("电源输出电压:" + output);
        return output;
    }
}

适配器角色(PowerAdapter.java):
public class PowerAdapter implements PowerTarget{
    private PowerAdaptee powerAdaptee;

    public PowerAdapter(PowerAdaptee powerAdaptee) {
        super();
        this.powerAdaptee = powerAdaptee;
    }

    @Override
    public int output5V() {
        int output = powerAdaptee.output220V();
        System.out.println("电源适配器开始工作,此时输出电压是:" + output);
        output = output/44;
        System.out.println("电源适配器工作完成,此时输出电压是:" + output);
        return output;
    } 
}

 

参考文章:

https://www.cnblogs.com/heliusKing/p/11577837.html

https://www.cnblogs.com/mingmingcome/p/9810731.html

 

 

 

 

 

 

 

发布了142 篇原创文章 · 获赞 345 · 访问量 45万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章