设计模式(6)——建造者模式

本文介绍建造者模式的概念和应用。

基本思想和原则

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

使用Builder类封装类实例的创建过程,客户代码使用各个Builder来构建对象而不是直接使用new创建类实例。

动机

当一个类中某个方法中的内部调用顺序不同,会产生不同的结果时,可以考虑使用建造者模式。将产生特定调用顺序的类实例用Builder进行封装,供客户代码使用可以简化整个对象创建过程。当需要产生新的调用顺序地类实例时,只需要创建对应的Builder即可。

实现

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
public abstract class Robot {
private ArrayList<String> actionSequence = new ArrayList<String>();

protected abstract void speak();

protected abstract void walk();

protected abstract void think();

public final void demo() {
for (int i = 0; i < this.actionSequence.size(); i++) {
String action = this.actionSequence.get(i);
if (action.equalsIgnoreCase("speak")) {
this.speak();
} else if (action.equalsIgnoreCase("walk")) {
this.walk();
} else if (action.equalsIgnoreCase("think")) {
this.think();
}
}
}

public final void setActionSequence(ArrayList actionSequence) {
this.actionSequence = actionSequence;
}
}

public class RobotA extends Robot {
@Override
protected void speak() {
System.out.println("RobotA speak...");
}

@Override
protected void walk() {
System.out.println("RobotA walk...");
}

@Override
protected void think() {
System.out.println("RobotA think...");
}
}

public class RobotB extends Robot {
@Override
protected void speak() {
System.out.println("RobotB speak...");
}

@Override
protected void walk() {
System.out.println("RobotB walk...");
}

@Override
protected void think() {
System.out.println("RobotB think...");
}
}

public abstract class RobotBuilder {
public abstract void setActionSequence(ArrayList<String> actionSequence);

public abstract Robot getRobot();
}

public class RobotABuilder extends RobotBuilder {
private RobotA robotA = new RobotA();

public void setActionSequence(ArrayList<String> actionSequence) {
this.robotA.setActionSequence(actionSequence);
}

public Robot getRobot() {
return this.robotA;
}
}

public class RobotBBuilder extends RobotBuilder {
private RobotB robotB = new RobotB();

public void setActionSequence(ArrayList<String> actionSequence) {
this.robotB.setActionSequence(actionSequence);
}

public Robot getRobot() {
return this.robotB;
}
}

public class Test {
public static void main(String[] args) {
ArrayList<String> actionSequence1 = new ArrayList<String>();
actionSequence1.add("speak");
actionSequence1.add("think");
actionSequence1.add("walk");

ArrayList<String> actionSequence2 = new ArrayList<String>();
actionSequence1.add("think");
actionSequence1.add("walk");
actionSequence1.add("speak");

RobotBuilder robotABuilder = new RobotABuilder();
RobotBuilder robotBBuilder = new RobotBBuilder();

robotABuilder.setActionSequence(actionSequence1);
robotABuilder.getRobot().demo();

System.out.println("\n");

robotABuilder.setActionSequence(actionSequence2);
robotABuilder.getRobot().demo();

System.out.println("\n");

robotBBuilder.setActionSequence(actionSequence1);
robotBBuilder.getRobot().demo();

System.out.println("\n");

robotBBuilder.setActionSequence(actionSequence2);
robotBBuilder.getRobot().demo();

}
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
RobotA speak...
RobotA think...
RobotA walk...

RobotA think...
RobotA walk...
RobotA speak...

RobotB speak...
RobotB think...
RobotB walk...

RobotB think...
RobotB walk...
RobotB speak...

上面的代码中,机器人可以有说话、走路和思考三种动作,demo方法用来执行机器人演示,我们想随意组合这些动作为一个动作序列来演示,。因此动作序列是可配置的。由于动作序列可以多种多样,使用建造者模式可以将各个动作序列封装在各个Builder中,客户代码直接调用Builder即可创建具有特定动作序列的机器人。

优点

建造者模式对一个类产生具体实例做了相应的封装,使客户代码不需要了解具体类的内部细节,可以直接使用相应的Builder来创建实例。各个Builder之间具有很好的隔离性,都可以独立做改变而不会互相影响。