来源:https://blog.csdn.net/ayunlong/article/details/130298095?spm=1001.2014.3001.5502

Java设计模式-建造者模式(Builder Pattern)

工厂模式关注的是构建结果,一个工厂生产一类对象;而建造者模式关注的是构建过程,调用不同的方法生产不同的对象。

什么是建造者模式

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

建造者模式一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

建造者模式主要包含4个角色:

  • 抽象建造者(Builder):要构建的目标对象所需要的“零部件”,大多是接口
  • 具体建造者(ConcreteBuilder):Builder的实现类,提供创建方法以及产品实例
  • 产品类(Product):要构建的对象,内部包含很多其他的“零部件对象”
  • 指挥者类(Director):负责调用Builder的方法构建对象,返回实例,对调用者屏蔽了具体的构建过程,构建者一般只与指挥者类打交道

建造者模式的实现

还是举一个造车的例子,一辆汽车需要窗户、座椅、轮胎等,而每个零部件都会有单独的厂商,汽车生产厂家不过是使用零部件组装为一辆汽车。

该例子包含的4个角色:

  1. 抽象建造者(Builder):ICarBuilder
  2. 具体建造者(ConcreteBuilder):CarBuilder
  3. 产品类(Product):Car
  4. 指挥者类(Director):CarDirector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package org.builderPattern.version1;

/**
* 产品类
*/
public class Car {
private String window;
private String tyre;
private String seat;
private boolean ai;

public boolean getAi() {
return ai;
}

public void setAi(boolean ai) {
this.ai = ai;
}

public String getWindow() {
return window;
}

public void setWindow(String window) {
this.window = window;
}

public String getTyre() {
return tyre;
}

public void setTyre(String tyre) {
this.tyre = tyre;
}

public String getSeat() {
return seat;
}

public void setSeat(String seat) {
this.seat = seat;
}

@Override
public String toString() {
String rs = "这款汽车有:" + this.getSeat() + "、" + this.getTyre() + "、" + this.getWindow();
if(this.getAi()){
rs += "、自动驾驶";
}
return rs;
}
}

package org.builderPattern.version1;

/**
* 抽象建造者
*/
public interface ICarBuilder {
public ICarBuilder setWindows(String window);
public ICarBuilder setSeat(String seat);
public ICarBuilder setTyre(String tyre);
public ICarBuilder setAI(boolean ai);

public Car createCar();
}

package org.builderPattern.version1;

/**
* 具体建造者
*/
public class CarBuilder implements ICarBuilder{
private Car car = new Car();
@Override
public ICarBuilder setWindows(String window) {
this.car.setWindow(window);
System.out.println("给汽车安装[" + window + "]");
return this;
}

@Override
public ICarBuilder setSeat(String seat) {
this.car.setSeat(seat);
System.out.println("给汽车安装[" + seat + "]");
return this;
}

@Override
public ICarBuilder setTyre(String tyre) {
this.car.setTyre(tyre);
System.out.println("给汽车安装[" + tyre + "]");
return this;
}

@Override
public ICarBuilder setAI(boolean ai) {
this.car.setAi(ai);
if (ai){
System.out.println("给汽车安装[自动驾驶]");
}
return this;
}

@Override
public Car createCar() {
return this.car;
}

}

package org.builderPattern.version1;

/**
* 指挥者
*/
public class CarDirector {
public Car createCar(ICarBuilder carBuilder){
carBuilder.setSeat("加热座椅")
.setTyre("耐磨轮胎")
.setWindows("普通窗户");
Car car = carBuilder.createCar();
return car;
}

public Car createAICar(ICarBuilder carBuilder){
carBuilder.setSeat("加热座椅")
.setTyre("耐磨轮胎")
.setWindows("普通窗户")
.setAI(true);
Car car = carBuilder.createCar();
return car;
}

}

package org.builderPattern.version1;

public class Client {
public static void main(String[] args) {
CarDirector director = new CarDirector();
Car car = director.createCar(new CarBuilder());
System.out.println(car.toString());

System.out.println("---------------------------------");
Car aiCar = director.createAICar(new CarBuilder());
System.out.println(aiCar);
}
}

// 运行结果
给汽车安装[加热座椅]
给汽车安装[耐磨轮胎]
给汽车安装[普通窗户]
这款汽车有:加热座椅、耐磨轮胎、普通窗户
---------------------------------
给汽车安装[加热座椅]
给汽车安装[耐磨轮胎]
给汽车安装[普通窗户]
给汽车安装[自动驾驶]
这款汽车有:加热座椅、耐磨轮胎、普通窗户、自动驾驶

案例中Client使用CarDirector指挥CarBuilder创造Car对象,Client并没有直接接触到CarBuilder类,这符合迪米特法则:只和朋友交流,不和陌生人说话,实现解耦

在创建的两个Car中,一个有自动驾驶一个没有,CarBuilder通过链式调用精准的控制Car类创建的过程,将复杂的创建步骤,分解到不同的方法中,使创建过程更加清晰。总结下建造者模式的优缺点:

优点:

  • 解耦,调用者无需知道构建细节,将产品本身与创建过程解耦,相同的创建过程可以创建不同的产品对象
  • 灵活,指挥者只调用建造者建造产品,新增新的建造者无需修改原有类库代码,扩展方便,符合开闭原则,一般产品类和建造者是比较稳定的。
  • 精细,复杂的创建过程拆解为不同方法,灵活调用,实现组装

缺点:

  • 建造者模式所创建的产品一般具有较多的额共同点,如果产品间差别很大时不适用,可以考虑工厂模式
  • 如果产品过于复杂,会导致定义过多的建造者类来实现这类变化,导致系统庞大

适用场景:

  • 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
  • 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
  • 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。