Home
avatar

yuanjh

设计模式_02创建型

说明

工厂

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题
何时使用:计划不同条件下创建不同实例时
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行。
应用实例:
1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
2、Hibernate 换数据库只需换方言和驱动就可以。
优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
使用场景:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

是不是看起来复杂?其实呢?真正的工厂根本没这么多东西。。
左侧的接口shape,本质上为了体现6原则中的“依赖倒转”原则,如果我们可以确保,我们对象是单一对象,并且这个对象未来也不可能增加同类变体。那么没必要每个对象都写一个接口,死套教科书。同样右侧的接口定义基本也是本着同样思路。而真正的工厂方法是什么?就是ShapeFacitory一个实体而已。
设计模式原本就是对大型软件开发参考的,所以整体设计偏向于“理论化”,“理想化”,所有动能通过接口实现,每个接口最好完全隔离。这样的划分对于大模块划分没问题,但是对于日常小软件开发基本是负作用,带来好处不足弥补代码结构复杂度,和代码量提升引起的修改和维护的负作用(代码就是负债,代码越多出错概率越大,修改成本越高)。

真正的工厂方法代码只有这么一个案例:

public class ShapeFactory {
    
   //使用 getShape 方法获取形状类型的对象
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

可以进一步简化为

if str.equals(xxxxx):
    return new xx()

其他的多余部分都是为了满足“6大原则”的”政治任务”.

典型调用

//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");

//调用 Rectangle 的 draw 方法
shape2.draw();

抽象工厂

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
按照工厂的方式,只提炼干货

看起来负责,真正的内容只是AbstractFactory的实现部分,这里个工厂返回的是工厂,所以抽象工厂其实更适合称之为“双层工厂” 代码样例:第一层

public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}

第二层(就是普通工厂)

public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }       
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }

典型调用:

 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");

      //获取形状为 Circle 的对象
      Shape shape1 = shapeFactory.getShape("CIRCLE");

      //调用 Circle 的 draw 方法
      shape1.draw();

单例

这个没太多可以看的,就是创建对象。
这个对象特殊之处在于全局就一个实例,这里暗坑比较多,最好的方法,使用时直接copy过来模板就行了

java而言就是,静态内部类,多线程安全,代码简洁,最保险版本

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}   

原型

利用已有的一个原型对象,快速地生成和原型对象一样的实例。
原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。
典型应用

 public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;
   }

建造者

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序

最核心的是builder和dirctor
director

class Director
{
    private Builder builder;
    public Director(Builder builder)
    {
        this.builder=builder;
    }
    //产品构建与组装方法
    public Product construct()
    {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}

builder

abstract class Builder
{
    //创建产品对象
    protected Product product=new Product();
    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();
    //返回产品对象
    public Product getResult()
    {
        return product;
    }
}

典型调用:

 public static void main(String[] args)
    {
        Builder builder=new ConcreteBuilder();
        Director director=new Director(builder);
        Product product=director.construct();
        product.show();
    }

可以看出,直接返回product的是Director,但实际是通过Director内部持有的builder返回。
Director通过定义builder方法的不同执行流对过程进行多态(如果需要不同的流程则新定义Director重写
builder通过对相同执行流程的不同具体实现进行多态(也就是相同执行流不同具体实现则定义builder重写)
例如:
高端车:加工-上漆-装轮胎-洗车(水洗)
一般车: 加工-装轮胎-上漆-洗车(酒精洗)
流程的不同通过不同Director实现。执行的细节不同通过builder实现。
其本质上是一种动作拆分方法Or功能拆分方法,虽然实际用作建造者场景比较少,但后续其他设计模式基本都是类似套路。本质上就是动作拆分,拆分给不同的对象,然后需要重修修改时,只需要在合适的层次重写另一个对象就行了(避免了对旧对象的改动)。

设计模式