设计模式_02创建型

说明

工厂

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
}

可以进一步简化为

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

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

典型调用

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

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

抽象工厂

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

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

1
2
3
4
5
6
7
8
9
10
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;
}
}

第二层(就是普通工厂)

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

典型调用:

1
2
3
4
5
6
7
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");

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

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

单例

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

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

1
2
3
4
5
6
7
8
9
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 读取二进制流。
典型应用

1
2
3
4
5
6
7
8
9
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}

建造者

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

最核心的是builder和dirctor
director

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}
}

典型调用:

1
2
3
4
5
6
7
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功能拆分方法,虽然实际用作建造者场景比较少,但后续其他设计模式基本都是类似套路。本质上就是动作拆分,拆分给不同的对象,然后需要重修修改时,只需要在合适的层次重写另一个对象就行了(避免了对旧对象的改动)。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×