sunxin's Studio.

建造者(Builder)设计模式

字数统计: 1.7k阅读时长: 7 min
2018/12/07 Share

建造者模式(Builder Patter)

概述

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式又称为生成器模式。

建造者模式通用类图

  • Protuct产品类
  • Builder建造者规范

规范产品的组建,一般由子类实现。

  • ConcreteBuilder具体建造者类

实现接口定义的所有方法,并返回一个组建好的对象。

  • Director导演类

负责安排已有模块的顺序,然后告诉Builder开始建造。

使用场景

  • 相同的方法,不同的执行顺序,产生不同的事件后果时,可以采用建造者模式
  • 多个部件或零件,都可以装配到一个对象中,但运行结果又不相同时,可以使用建造者模式。
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
  • 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。

举个栗子

现在有如下场景:有一项业务是制作奔驰和宝马的汽车模型,要求模型有启动,停止,鸣笛,引擎有轰鸣声等四项功能,并且功能顺序都由客户来控制。客户要什么顺序的模型就得马上生产什么顺序的模型,而且还得是批量生产。

提供以下四种模型:

​ 奔驰A模型,先启动,后停止,没有引擎轰隆和喇叭

​ 奔驰B模型,先有引擎声,再启动,后停止

​ 宝马A模型,先鸣笛,再启动,后停止

​ 宝马B模型,直接启动

A客户需求:要3辆A型宝马车

B客户需求:要2辆B型奔驰车

我们需要:传入一个模型的顺序,就能直接返回一个汽车模型对象。

1,创建Product类,基类CarModel,BenzModel和BMWModel继承之。

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
/**
* 车辆模型的抽象类
*
* @author sunxin
*
*/
public abstract class CarModel {
// 各个方法执行的顺序
private ArrayList<String> sequence = new ArrayList<>();

// 汽车启动
protected abstract void start();

// 汽车停止
protected abstract void stop();

// 汽车鸣笛
protected abstract void alarm();

// 汽车引擎轰轰响
protected abstract void engineBoom();

// 汽车跑动
public void run() {
// 循环,谁在前,谁就先run
for (int i = 0; i < this.sequence.size(); i++) {
String actionName = this.sequence.get(i);
if (actionName.equalsIgnoreCase("start")) {
this.start();
} else if (actionName.equalsIgnoreCase("stop")) {
this.stop();
} else if (actionName.equalsIgnoreCase("alarm")) {
this.alarm();
} else if (actionName.equalsIgnoreCase("engineBoom")) {
this.engineBoom();
}
}
}

/**
* 允许用户自己设置一个顺序
* @param sequence
*/
public void setSequence(ArrayList<String> sequence) {
this.sequence = sequence;
}

}
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
/**
* 奔驰车模型
* @author sunxin
*
*/
public class BenzModel extends CarModel{

@Override
protected void start() {
System.out.println("奔驰车跑了...");
}

@Override
protected void stop() {
System.out.println("奔驰车停了...");
}

@Override
protected void alarm() {
System.out.println("奔驰车鸣笛了...");
}

@Override
protected void engineBoom() {
System.out.println("奔驰车引擎轰隆了...");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class BMWModel extends CarModel{

@Override
protected void start() {
System.out.println("宝马车跑了...");
}

@Override
protected void stop() {
System.out.println("宝马车停了...");
}

@Override
protected void alarm() {
System.out.println("宝马车鸣笛了...");
}

@Override
protected void engineBoom() {
System.out.println("宝马车引擎轰隆了...");
}

}
  1. 创建建造汽车的规范CarBuilder接口,要求传入一个顺序,设置后直接返回一个模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 汽车的建造者规范
*
* @author sunxin
*
*/
public interface CarBuilder {
/**
* 建造一个模型,需要一个建造顺序
* @param sequence
*/
void setSequence(ArrayList<String> sequence);

/**
* 顺序设置完毕,直接返回一个汽车模型
* @return
*/
CarModel getCarModel();
}
  1. 创建具体建造者类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 奔驰车建造者
*
* @author sunxin
*
*/
public class BenzBuilder implements CarBuilder {
private BenzModel benzModel = new BenzModel();
//设置建造顺序
@Override
public void setSequence(ArrayList<String> sequence) {
this.benzModel.setSequence(sequence);
}
//直接返回模型
@Override
public CarModel getCarModel() {
return benzModel;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 宝马车建造者
* @author sunxin
*
*/
public class BMWBuilder implements CarBuilder{

private BMWModel bmwModer = new BMWModel();
@Override
public void setSequence(ArrayList<String> sequence) {
this.bmwModer.setSequence(sequence);
}

@Override
public CarModel getCarModel() {
return bmwModer;
}

}
  1. 创建导演类Director,生产各个型号的车
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
/**
* 导演类,可以指定生产车的各种型号.起到封装的作用,避免高层模块深入到建造者内部的实现类
*
* @author sunxin
*
*/
public class Director {
private ArrayList<String> sequence = new ArrayList<>();

BenzBuilder benzBuilder = new BenzBuilder();
BMWBuilder bmwBuilder = new BMWBuilder();

/**
* 生产奔驰车A型号,先start,后stop,没有引擎轰隆和喇叭
* @return
*/
public BenzModel getBenzAModel(){
this.sequence.clear();//清理一下,避免数据混淆

this.sequence.add("start");
this.sequence.add("stop");

benzBuilder.setSequence(sequence);
CarModel benzCarModel = benzBuilder.getCarModel();

return (BenzModel) benzCarModel;
}


/**
* 生产奔驰车B型号,引擎声,start,后stop,没有喇叭
* @return
*/
public BenzModel getBenzBModel(){
this.sequence.clear();//清理一下,避免数据混淆

this.sequence.add("engineBoom");
this.sequence.add("start");
this.sequence.add("stop");

benzBuilder.setSequence(sequence);
CarModel benzCarModel = benzBuilder.getCarModel();

return (BenzModel) benzCarModel;
}


/**
* 生产宝马车A型号,先按喇叭,启动,停止
* @return
*/
public BMWModel getBMWAModel(){
this.sequence.clear();//清理一下,避免数据混淆

this.sequence.add("alarm");
this.sequence.add("start");
this.sequence.add("stop");

bmwBuilder.setSequence(sequence);
CarModel bmwCarModel = bmwBuilder.getCarModel();

return (BMWModel) bmwCarModel;
}

/**
* 生产宝马车B型号,上去就跑
* @return
*/
public BMWModel getBMWBModel(){
this.sequence.clear();//清理一下,避免数据混淆

this.sequence.add("start");

bmwBuilder.setSequence(sequence);
CarModel bmwCarModel = bmwBuilder.getCarModel();

return (BMWModel) bmwCarModel;
}

}
  1. 最后是客户端调用Client类,根据需求,批量生产所需型号的车辆
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
/**
* 客户端
*
* @author sunxin
*
*/
public class Client {
public static void main(String[] args) {
/**
* 改造2,加入导演类Director,控制顺序,批量建造
*/

Director director = new Director();

//建造3辆A型宝马车
for (int i = 0; i < 3; i++) {
BMWModel bmwaModel = director.getBMWAModel();
bmwaModel.run();
System.out.println("---");
}
System.out.println("------------");

//建造2辆B型奔驰车
for (int i = 0; i < 2; i++) {
BenzModel benzBModel = director.getBenzBModel();
benzBModel.run();
System.out.println("---");
}

}
}
  1. 运行的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
宝马车鸣笛了...
宝马车跑了...
宝马车停了...
---
宝马车鸣笛了...
宝马车跑了...
宝马车停了...
---
宝马车鸣笛了...
宝马车跑了...
宝马车停了...
---
------------
奔驰车引擎轰隆了...
奔驰车跑了...
奔驰车停了...
---
奔驰车引擎轰隆了...
奔驰车跑了...
奔驰车停了...
---
  1. 完毕

建造者模式的优点

  • 封装性好,不需要关心建造者内部的实现细节
  • 建造者独立,容易扩展
  • 便于控制细节风险

建造者模式与工厂设计模式的区别

  • 建造者模式最主要的功能是调用方法的顺序安排,通俗的就是零件的装配,顺序不同 产生的对象不同
  • 工厂设计模式重点是创建,创建零件是它的主要职责,组装顺序则不是它所关心的。
CATALOG
  1. 1. 建造者模式(Builder Patter)
    1. 1.1. 概述
    2. 1.2. 使用场景
    3. 1.3. 举个栗子
    4. 1.4. 建造者模式的优点
    5. 1.5. 建造者模式与工厂设计模式的区别