前面的工厂模式可以用来创建大量简单的类。但是现象一下像电脑这样一个复杂的产品。每台电脑都有很多部分组成,包括CPU,光驱,显卡,内存.......最终的电脑产品需要按一定的顺序,先安装CPU然后内存等等,在组装过程没有结束之前,电脑是无法使用的。由于这一组装过程可能很复杂,而且可能会经常变动。那么就有必要将这易变的过程抽象出一个外部电脑组装者来负责产品的组装过程。另外,客户对于电脑产品肯定会有一些偏好,比如某些人喜欢DELL电脑,有些人喜欢IBM电脑,这些电脑生产者的组装产品的方式几乎雷同,也就是说针对客户的不同需要,电脑组装者的构造过程可以适合于不同的生产者。
对于这样的有多个零件组成的复杂产品的组装过程,就可以使用Builder建造者模式来完成。
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
我们来看看其UML模型:
建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者(ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的方法:一个是建造方法如BuliderCPU,BuilderBoard等,另一个是结果返还方法GetComputer。
具体建造者(Concrete Builder)角色:担任这个角色的是于应用程序紧密相关的类,它们在应用程序调用下创建产品实例,这里为DellBuilder类,IBMBuilder类。这个角色主要完成实现Builder角色提供的接口,一步一步完成创建产品实例的过程。
指导者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。导演者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象,这里为ComputerDirector类。
我们来看看其代码实现(C#):
1
using System;
2
using System.Collections;
3![](/Images/OutliningIndicators/None.gif)
4![](/Images/OutliningIndicators/None.gif)
5
namespace BuilderPattom
6![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
7![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
8
///============== Program Description==============
9
///Name:BuilderPattom.cs
10
///Objective:BuilderPattom
11
///Date:2006-04-28
12
///Written By coffee.liu
13
///================================================
14
/// </summary>
15
class Class1
16![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
17![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
18
/// 应用程序的主入口点。
19
/// </summary>
20
[STAThread]
21
static void Main(string[] args)
22![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
23
Hashtable PH;
24
ComputerDirector CD=new ComputerDirector();
25
Builder B1=new DellBuilder();
26
Builder B2=new IBMBuilder();
27
CD.Create(B1);
28
PH=(B1.GetComputer()) as Hashtable;
29
Console.WriteLine("Dell Computers![](https://www.cnblogs.com/Images/dot.gif)
..");
30
Console.WriteLine("Board:"+Convert.ToString(PH["Board"]));
31
Console.WriteLine("CPU:"+Convert.ToString(PH["CPU"]));
32
Console.WriteLine("Menory:"+Convert.ToString(PH["Menory"]));
33
CD.Create(B2);
34
PH=(B2.GetComputer()) as Hashtable;
35
Console.WriteLine("IBM Computers![](https://www.cnblogs.com/Images/dot.gif)
..");
36
Console.WriteLine("Board:"+Convert.ToString(PH["Board"]));
37
Console.WriteLine("CPU:"+Convert.ToString(PH["CPU"]));
38
Console.WriteLine("Menory:"+Convert.ToString(PH["Menory"]));
39![](/Images/OutliningIndicators/InBlock.gif)
40
}
41
}
42
//abstractBuilder
43![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
abstract class Builder
{
44
abstract public Hashtable Createhash();
45
abstract public void BuilderCpu();
46
abstract public void BuilderBoard();
47
abstract public void BuilderMenory();
48
abstract public Object GetComputer();
49
}
50![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
class DellBuilder:Builder
{
51
private Hashtable myHashTable;
52
public override Hashtable Createhash()
53![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
54
return myHashTable=new Hashtable();
55
}
56![](/Images/OutliningIndicators/InBlock.gif)
57
override public void BuilderCpu()
58![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
59
myHashTable.Add("CPU","Intel");
60
}
61
public override void BuilderBoard()
62![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
63
myHashTable.Add("Board","DellBoard");
64
}
65
public override void BuilderMenory()
66![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
67
myHashTable.Add("Menory","DellMenory");
68
}
69
public override Object GetComputer()
70![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
71
return myHashTable;
72
}
73
}
74
class IBMBuilder:Builder
75![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
76
private Hashtable myHashTable;
77
public override Hashtable Createhash()
78![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
79
return myHashTable=new Hashtable();
80
}
81![](/Images/OutliningIndicators/InBlock.gif)
82
override public void BuilderCpu()
83![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
84
myHashTable.Add("CPU","Intel");
85
}
86
public override void BuilderBoard()
87![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
88
myHashTable.Add("Board","IBMBoard");
89
}
90
public override void BuilderMenory()
91![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
92
myHashTable.Add("Menory","IBMMenory");
93
}
94
public override Object GetComputer()
95![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
96
return myHashTable;
97
}
98
}
99
//Director
100![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
class ComputerDirector
{
101![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void Create(Builder ABuilder)
{
102
ABuilder.Createhash();
103
ABuilder.BuilderBoard();
104
ABuilder.BuilderCpu();
105
ABuilder.BuilderMenory();
106
}
107
}
108
}
109![](/Images/OutliningIndicators/None.gif)
下面的代码为实现同样的功能的Pascal代码:
1
program BuilderPattom;
2
//============== Program Description==============
3
//Name:BuilderPattom.dpr
4
//Objective:BuilderPattom
5
//Date:2006-04-29
6
//Written By coffee.liu
7
//================================================
8
{$APPTYPE CONSOLE}
9![](/Images/OutliningIndicators/None.gif)
10
uses
11
SysUtils,Classes;
12
//零件
13
type Part=record
14
Name:string;
15
Valual:string;
16
end;
17
PPart=^Part;
18
//具体产品
19
type Product=class
20
private
21
AProduct:TList;
22
public
23
constructor Create;
24
procedure Add(APart:PPart);
25
procedure Say();
26
destructor Destroy();override;
27
end;
28
//建造者
29
type Builder=class
30
procedure BuilderCpu();virtual;abstract;
31
procedure BuilderBoard();virtual;abstract;
32
procedure BuilderMenory();virtual;abstract;
33
function GetComputer:Tobject;virtual;abstract;
34
end;
35
//具体建造者
36
type DellBuilder=class(Builder)
37
private AProduct:Product;
38
public
39
procedure BuilderCpu();override;
40
procedure BuilderBoard();override;
41
procedure BuilderMenory();override;
42
function GetComputer:Tobject;override;
43
constructor Create();
44
destructor Destroy();override;
45![](/Images/OutliningIndicators/None.gif)
46
end;
47
//具体建造者
48
type IBMBuilder=class(Builder)
49
private AProduct:Product;
50
public
51
procedure BuilderCpu();override;
52
procedure BuilderBoard();override;
53
procedure BuilderMenory();override;
54
function GetComputer:Tobject;override;
55
constructor Create();
56
destructor Destroy();override;
57
end;
58
//指导者
59
type ComputerDirector=class
60
constructor Create(ABuilder:Builder);
61
end;
62![](/Images/OutliningIndicators/None.gif)
63![](/Images/OutliningIndicators/None.gif)
64
{ DellBuilder }
65![](/Images/OutliningIndicators/None.gif)
66
procedure DellBuilder.BuilderBoard;
67
var
68
Pa:PPart;
69
begin
70
inherited;
71
new(Pa); //创建指针,以下同
72
Pa^.Name:='DELL';
73
Pa^.Valual:='Board';
74
AProduct.Add(pa);
75
end;
76![](/Images/OutliningIndicators/None.gif)
77
procedure DellBuilder.BuilderCpu;
78
var
79
Pa:PPart;
80
begin
81
inherited;
82
new(Pa);
83
Pa^.Name:='DELL';
84
Pa^.Valual:='Cpu';
85
AProduct.Add(pa);
86
end;
87![](/Images/OutliningIndicators/None.gif)
88
procedure DellBuilder.BuilderMenory;
89
var
90
Pa:PPart;
91
begin
92
inherited;
93
new(Pa);
94
Pa^.Name:='DELL';
95
Pa^.Valual:='Menory';
96
AProduct.Add(pa);
97
end;
98![](/Images/OutliningIndicators/None.gif)
99
constructor DellBuilder.Create;
100
begin
101
AProduct:=Product.Create;
102
end;
103![](/Images/OutliningIndicators/None.gif)
104
destructor DellBuilder.Destroy;
105
begin
106
AProduct.Free;
107
inherited Destroy;
108
end;
109![](/Images/OutliningIndicators/None.gif)
110
function DellBuilder.GetComputer: Tobject;
111
begin
112
result:=AProduct;
113
end;
114![](/Images/OutliningIndicators/None.gif)
115
{ IBMBuilder }
116![](/Images/OutliningIndicators/None.gif)
117
procedure IBMBuilder.BuilderBoard;
118
var
119
Pa:PPart;
120
begin
121
inherited;
122
new(Pa);
123
Pa^.Name:='IBM';
124
Pa^.Valual:='Board';
125
AProduct.Add(pa);
126
end;
127![](/Images/OutliningIndicators/None.gif)
128
procedure IBMBuilder.BuilderCpu;
129
var
130
Pa:PPart;
131
begin
132
inherited;
133
new(Pa);
134
Pa^.Name:='IBM';
135
Pa^.Valual:='Cpu';
136
AProduct.Add(pa);
137
end;
138![](/Images/OutliningIndicators/None.gif)
139
procedure IBMBuilder.BuilderMenory;
140
var
141
Pa:PPart;
142
begin
143
inherited;
144
new(Pa);
145
Pa^.Name:='IBM';
146
Pa^.Valual:='Menory';
147
AProduct.Add(pa);
148
end;
149![](/Images/OutliningIndicators/None.gif)
150
constructor IBMBuilder.Create;
151
begin
152
AProduct:=Product.Create;
153
end;
154![](/Images/OutliningIndicators/None.gif)
155
destructor IBMBuilder.Destroy;
156
begin
157
AProduct.Free;
158
inherited Destroy;
159
end;
160![](/Images/OutliningIndicators/None.gif)
161
function IBMBuilder.GetComputer: Tobject;
162
begin
163
result:=AProduct;
164
end;
165![](/Images/OutliningIndicators/None.gif)
166
{ ComputerDirector }
167![](/Images/OutliningIndicators/None.gif)
168
constructor ComputerDirector.Create(ABuilder: Builder);
169
begin
170
ABuilder.BuilderBoard();
171
ABuilder.BuilderCpu();
172
ABuilder.BuilderMenory()
173
end;
174![](/Images/OutliningIndicators/None.gif)
175
{ Product }
176![](/Images/OutliningIndicators/None.gif)
177
procedure Product.Add(APart: PPart);
178
begin
179
AProduct.Add(APart);
180
end;
181![](/Images/OutliningIndicators/None.gif)
182
constructor Product.Create;
183
begin
184
AProduct:=TList.Create;
185
end;
186![](/Images/OutliningIndicators/None.gif)
187
destructor Product.Destroy;
188
begin
189![](/Images/OutliningIndicators/None.gif)
190
AProduct.Free;
191
inherited Destroy;
192
end;
193![](/Images/OutliningIndicators/None.gif)
194
procedure Product.Say;
195
var
196
i:integer;
197
begin
198
for i:=0 to AProduct.Count-1 do
199
begin
200
Writeln(string(PPart(AProduct.Items[i])^.Name)+':'+PPart(AProduct.Items[i])^.Valual);
201
Dispose(PPart(AProduct.Items[i]));//释放指针
202
end;
203![](/Images/OutliningIndicators/None.gif)
204
end;
205
var
206
ABuilder,BBuilder:Builder;
207
DELLProduct,IBMProduct:Product;
208
begin
209
try
210
ABuilder:=DellBuilder.Create;
211
ComputerDirector.Create(ABuilder);
212
DELLProduct:=Product(ABuilder.GetComputer);
213
DELLProduct.Say;
214
BBuilder:=IBMBuilder.Create;
215
ComputerDirector.Create(BBuilder);
216
IBMProduct:=Product(BBuilder.GetComputer);
217
IBMProduct.Say;
218
finally
219
DELLProduct.Free;
220
IBMProduct.Free;
221
end;
222
end.
对于Pascal语言来说要特别注意对象的释放,因为作为Pascal可没有垃圾回收机制,我们应用了TList对象,这个对象是不会自动释放自己的。而且我们使用了指针,这也要进行释放。仔细看看程序的Destroy的运行流程,就会明白。
使用Builder模式的好处,可以让产品的组装过程同具体零件的生产分离开来,便于今后组成流程的独立演化,同时对于用户来说,他不需要知道具体的零件生产细节,他只要关心最终获得的产品就可以了。
在什么情况下需要使用建造者呢
1、 需要生成的产品对象有复杂的内部结构。
2、 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
建造者模式的效果:
1.生成器语序读者改变产品的内部表示,同时也隐藏呢产品如何组装的细节。
2.每个特定的生成器独立于其他的生成器,同时独立于程序的其他部分,这一点提高了对象的模块性,并使添加其他的生成器变得相对简单。
3.由于每个生成器是根据数据一步一步构建最终结果,所以能精确地控制生成器构建的每个结果。
生成器模式有点类似于抽象工厂模式,两者都返回由许多方法和对象组成的类,他们之间的主要差别是,抽象工厂返回的是一系列相关的类,而生成器是根据提供给它的数据一步一步地构建一个复杂的对象。