👉文章示例代码👈

定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

用户只需指定需要建造的类型就可以得到它们,建造过程及细节不需要知道。

建造者模式注重于方法的调用顺序,而工厂模式注重于创建产品。

四要素

标准建造者模式有四个要素:

  • 产品类:既可以是具体的实体类,也可以是抽象类与其具体实现组成。
  • 抽象建造者:接口或者抽象类,将具体的实现过程移交给子类。
  • 具体建造者:抽象建造者的具体实现类,用于构建产品。
  • 指挥者类:调用合适的建造者方法来构建产品。

场景示例

笔者这里以攒电脑为例。攒机需要购买一些配置,例如:CPU、主板、内存条、硬盘、显卡、机箱、电源、显示器等。然后按照自己的需求和喜好将这些配置攒起来组装成电脑,满足自己的个性化需求。当然也会有一些攒机的商家,来帮用户处理攒机的过程。

创建产品类

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
/**
* @author zhh
* @description 电脑类
* @date 2020-02-11 14:01
*/
public class Computer {

/**
* cpu
*/
private String cpu;

/**
* 主板
*/
private String mainboard;

/**
* 内存
*/
private String memory;

/**
* 硬盘
*/
private String hardDisk;

/**
* 显卡
*/
private String gpu;

/**
* 机箱
*/
private String crate;

/**
* 电源
*/
private String powerSupply;

/**
* 显示器
*/
private String monitor;

// 此处省略getter、setter方法

@Override
public String toString() {
return "Computer{" + "cpu='" + cpu + '\'' + ", mainboard='" + mainboard + '\'' + ", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' + ", gpu='" + gpu + '\'' + ", crate='" + crate + '\'' +
", powerSupply='" + powerSupply + '\'' + ", monitor='" + monitor + '\'' + '}';
}
}

创建抽象建造者

抽象电脑建造者类中,额外提供一个组装电脑的方法,其返回参数为产品类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author zhh
* @description 抽象电脑建造者类
* @date 2020-02-11 14:32
*/
public abstract class ComputerBuilder {

public abstract void buyCpu(String cpu);
public abstract void buyMainboard(String mainboard);
public abstract void buyMemory(String memory);
public abstract void buyHardDisk(String hardDisk);
public abstract void buyGpu(String gpu);
public abstract void buyCrate(String crate);
public abstract void buyPowerSupply(String powerSupply);
public abstract void buyMonitor(String monitor);

/**
* 组装电脑
*/
public abstract Computer assembleComputer();
}

创建具体建造者

创建具体的建造者类,继承我们的抽象创建者,实现抽象方法。

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
/**
* @author zhh
* @description 实际的电脑建造者类
* @date 2020-02-11 14:41
*/
public class ComputerActualBuilder extends ComputerBuilder {

private Computer computer = new Computer();

@Override
public void buyCpu(String cpu) {
computer.setCpu(cpu);
}

@Override
public void buyMainboard(String mainboard) {
computer.setMainboard(mainboard);
}

@Override
public void buyMemory(String memory) {
computer.setMemory(memory);
}

@Override
public void buyHardDisk(String hardDisk) {
computer.setHardDisk(hardDisk);
}

@Override
public void buyGpu(String gpu) {
computer.setGpu(gpu);
}

@Override
public void buyCrate(String crate) {
computer.setCrate(crate);
}

@Override
public void buyPowerSupply(String powerSupply) {
computer.setPowerSupply(powerSupply);
}

@Override
public void buyMonitor(String monitor) {
computer.setMonitor(monitor);
}

@Override
public Computer assembleComputer() {
return computer;
}
}

创建指挥者类

攒机商家是我们的指挥者,商家推荐配置供用户购买参考,帮助用户进行组装。

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
/**
* @author zhh
* @description 商家类
* @date 2020-02-11 14:55
*/
public class Enterprise {

private ComputerBuilder computerBuilder;

public void setComputerBuilder(ComputerBuilder computerBuilder) {
this.computerBuilder = computerBuilder;
}

/**
* 组装电脑
*/
public Computer assembleComputer(String cpu, String mainboard,
String memory, String hardDisk,
String gpu, String crate,
String powerSupply, String monitor) {
computerBuilder.buyCpu(cpu);
computerBuilder.buyMainboard(mainboard);
computerBuilder.buyMemory(memory);
computerBuilder.buyHardDisk(hardDisk);
computerBuilder.buyGpu(gpu);
computerBuilder.buyCrate(crate);
computerBuilder.buyPowerSupply(powerSupply);
computerBuilder.buyMonitor(monitor);

return computerBuilder.assembleComputer();
}
}

测试类及输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @author zhh
* @description 测试类
* @date 2020-02-11 15:05
*/
public class Test {
public static void main(String[] args) {
ComputerBuilder computerBuilder = new ComputerActualBuilder();
Enterprise enterprise = new Enterprise();
enterprise.setComputerBuilder(computerBuilder);
Computer computer = enterprise.assembleComputer("Intel 酷睿i7 8700K",
"影驰B360M-M.2",
"影驰GAMER 8GB DDR4 2400",
"希捷Barracuda 1TB 7200转 64MB",
"七彩虹iGame750Ti 烈焰战神U-Twin-2GD5",
"金河田峥嵘Z30",
"航嘉WD600K",
"三星C27F390FHC");

System.out.println(computer);
}
}

测试类的输出结果如下:

Computer{cpu=’Intel 酷睿i7 8700K’, mainboard=’影驰B360M-M.2’, memory=’影驰GAMER 8GB DDR4 2400’, hardDisk=’希捷Barracuda 1TB 7200转 64MB’, gpu=’七彩虹iGame750Ti 烈焰战神U-Twin-2GD5’, crate=’金河田峥嵘Z30’, powerSupply=’航嘉WD600K’, monitor=’三星C27F390FHC’}

类结构图

以上示例类的结构图如下所示
image.png

我们可以看到我们的 Test 类和抽象建造者 ComputerBuilder 和产品类 Computer 都没有关系,只和指挥者类 Enterprise 、具体的建造者 ComputerActualBuilder 有关。

Test 类创建指挥者类 Enterprise,指挥者类 Enterprise 通过组合的方式使用 ComputerBuilder ,实际使用 ComputerActualBuilder 创建产品类 Computer

示例演进

上述示例建造者的使用方式只是一种标准的使用方式。

我们发现我们的指挥者类并不是必须的。我们可以不需要攒机商家帮忙组装,我们可以自己动手。

下面来进行代码的演进。

调整产品类

这里使用静态内部类,依靠链式调用的方式来调整产品类。

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
/**
* @author zhh
* @description 电脑类
* @date 2020-02-11 14:01
*/
public class Computer {

/**
* cpu
*/
private String cpu;

/**
* 主板
*/
private String mainboard;

/**
* 内存
*/
private String memory;

/**
* 硬盘
*/
private String hardDisk;

/**
* 显卡
*/
private String gpu;

/**
* 机箱
*/
private String crate;

/**
* 电源
*/
private String powerSupply;

/**
* 显示器
*/
private String monitor;

public Computer(ComputerBuilder computerBuilder) {
this.cpu = computerBuilder.cpu;
this.mainboard = computerBuilder.mainboard;
this.memory = computerBuilder.memory;
this.hardDisk = computerBuilder.hardDisk;
this.gpu = computerBuilder.gpu;
this.crate = computerBuilder.crate;
this.powerSupply = computerBuilder.powerSupply;
this.monitor = computerBuilder.monitor;
}

@Override
public String toString() {
return "Computer{" + "cpu='" + cpu + '\'' + ", mainboard='" + mainboard + '\'' + ", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' + ", gpu='" + gpu + '\'' + ", crate='" + crate + '\'' +
", powerSupply='" + powerSupply + '\'' + ", monitor='" + monitor + '\'' + '}';
}

/**
* 声明静态内部类
*/
public static class ComputerBuilder {
/**
* cpu
*/
private String cpu;

/**
* 主板
*/
private String mainboard;

/**
* 内存
*/
private String memory;

/**
* 硬盘
*/
private String hardDisk;

/**
* 显卡
*/
private String gpu;

/**
* 机箱
*/
private String crate;

/**
* 电源
*/
private String powerSupply;

/**
* 显示器
*/
private String monitor;

public ComputerBuilder buyCpu(String cpu){
this.cpu = cpu;
return this;
}

public ComputerBuilder buyMainboard(String mainboard){
this.mainboard = mainboard;
return this;
}

public ComputerBuilder buyMemory(String memory){
this.memory = memory;
return this;
}

public ComputerBuilder buyHardDisk(String hardDisk){
this.hardDisk = hardDisk;
return this;
}

public ComputerBuilder buyGpu(String gpu){
this.gpu = gpu;
return this;
}

public ComputerBuilder buyCrate(String crate){
this.crate = crate;
return this;
}

public ComputerBuilder buyPowerSupply(String powerSupply){
this.powerSupply = powerSupply;
return this;
}

public ComputerBuilder buyMonitor(String monitor){
this.monitor = monitor;
return this;
}

public Computer build() {
return new Computer(this);
}
}
}

测试类及输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author zhh
* @description 测试类
* @date 2020-02-11 15:05
*/
public class Test {
public static void main(String[] args) {
Computer computer = new Computer.ComputerBuilder()
.buyCpu("Intel 酷睿i7 8700K")
.buyMainboard("影驰B360M-M.2")
.buyMemory("影驰GAMER 8GB DDR4 2400")
.buyHardDisk("希捷Barracuda 1TB 7200转 64MB")
.buyGpu("七彩虹iGame750Ti 烈焰战神U-Twin-2GD5")
.buyCrate("金河田峥嵘Z30")
.buyPowerSupply("航嘉WD600K")
.buyMonitor("三星C27F390FHC")
.build();

System.out.println(computer);
}
}

测试类的输出结果如下:

Computer{cpu=’Intel 酷睿i7 8700K’, mainboard=’影驰B360M-M.2’, memory=’影驰GAMER 8GB DDR4 2400’, hardDisk=’希捷Barracuda 1TB 7200转 64MB’, gpu=’七彩虹iGame750Ti 烈焰战神U-Twin-2GD5’, crate=’金河田峥嵘Z30’, powerSupply=’航嘉WD600K’, monitor=’三星C27F390FHC’}

类结构图

以上演进的结构图如下所示
image.png

源码中的用例

  • java.lang.StringBuilderjava.lang.StringBuffer
  • Spring 中的 BeanDefinitionBuilder
  • MyBatis 中的 SqlSessionFactoryBuilder

总结

适用场景

  • 一个对象有非常复杂的内部结构(很多属性)
  • 想把复杂对象的创建和使用分离

优点

  • 封装性比较好,创建和使用分离
  • 扩展性好,建造类之间独立,在一定程度上解耦

缺点

  • 会产生多余的Builder对象
  • 产品内部结构发生变化,建造者都需要修改,成本比较大

参考