对于这样的有多个零件组成的复杂产品的组装过程,就可以使用Builder建造者模式来完成。
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
我们来看看其UML模型:建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者(ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的方法:一个是建造方法如BuliderCPU,BuilderBoard等,另一个是结果返还方法GetComputer。
具体建造者(Concrete Builder)角色:担任这个角色的是于应用程序紧密相关的类,它们在应用程序调用下创建产品实例,这里为DellBuilder类,IBMBuilder类。这个角色主要完成实现Builder角色提供的接口,一步一步完成创建产品实例的过程。
指导者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。导演者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象,这里为ComputerDirector类。
2using System.Collections;
3
4
5namespace BuilderPattom
6{
7 /// <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 {
17 /// <summary>
18 /// 应用程序的主入口点。
19 /// </summary>
20 [STAThread]
21 static void Main(string[] args)
22 {
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..");
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..");
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
40 }
41 }
42 //abstractBuilder
43 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 class DellBuilder:Builder{
51 private Hashtable myHashTable;
52 public override Hashtable Createhash()
53 {
54 return myHashTable=new Hashtable();
55 }
56
57 override public void BuilderCpu()
58 {
59 myHashTable.Add("CPU","Intel");
60 }
61 public override void BuilderBoard()
62 {
63 myHashTable.Add("Board","DellBoard");
64 }
65 public override void BuilderMenory()
66 {
67 myHashTable.Add("Menory","DellMenory");
68 }
69 public override Object GetComputer()
70 {
71 return myHashTable;
72 }
73 }
74 class IBMBuilder:Builder
75 {
76 private Hashtable myHashTable;
77 public override Hashtable Createhash()
78 {
79 return myHashTable=new Hashtable();
80 }
81
82 override public void BuilderCpu()
83 {
84 myHashTable.Add("CPU","Intel");
85 }
86 public override void BuilderBoard()
87 {
88 myHashTable.Add("Board","IBMBoard");
89 }
90 public override void BuilderMenory()
91 {
92 myHashTable.Add("Menory","IBMMenory");
93 }
94 public override Object GetComputer()
95 {
96 return myHashTable;
97 }
98 }
99 //Director
100 class ComputerDirector{
101 public void Create(Builder ABuilder){
102 ABuilder.Createhash();
103 ABuilder.BuilderBoard();
104 ABuilder.BuilderCpu();
105 ABuilder.BuilderMenory();
106 }
107 }
108}
109
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
10uses
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
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
63
64{ DellBuilder }
65
66procedure DellBuilder.BuilderBoard;
67var
68Pa:PPart;
69begin
70 inherited;
71 new(Pa); //创建指针,以下同
72 Pa^.Name:='DELL';
73 Pa^.Valual:='Board';
74 AProduct.Add(pa);
75end;
76
77procedure DellBuilder.BuilderCpu;
78var
79Pa:PPart;
80begin
81 inherited;
82 new(Pa);
83 Pa^.Name:='DELL';
84 Pa^.Valual:='Cpu';
85 AProduct.Add(pa);
86end;
87
88procedure DellBuilder.BuilderMenory;
89var
90Pa:PPart;
91begin
92 inherited;
93 new(Pa);
94 Pa^.Name:='DELL';
95 Pa^.Valual:='Menory';
96 AProduct.Add(pa);
97end;
98
99constructor DellBuilder.Create;
100begin
101 AProduct:=Product.Create;
102end;
103
104destructor DellBuilder.Destroy;
105begin
106 AProduct.Free;
107 inherited Destroy;
108end;
109
110function DellBuilder.GetComputer: Tobject;
111begin
112 result:=AProduct;
113end;
114
115{ IBMBuilder }
116
117procedure IBMBuilder.BuilderBoard;
118var
119Pa:PPart;
120begin
121 inherited;
122 new(Pa);
123 Pa^.Name:='IBM';
124 Pa^.Valual:='Board';
125 AProduct.Add(pa);
126end;
127
128procedure IBMBuilder.BuilderCpu;
129var
130Pa:PPart;
131begin
132 inherited;
133 new(Pa);
134 Pa^.Name:='IBM';
135 Pa^.Valual:='Cpu';
136 AProduct.Add(pa);
137end;
138
139procedure IBMBuilder.BuilderMenory;
140var
141Pa:PPart;
142begin
143 inherited;
144 new(Pa);
145 Pa^.Name:='IBM';
146 Pa^.Valual:='Menory';
147 AProduct.Add(pa);
148end;
149
150constructor IBMBuilder.Create;
151begin
152 AProduct:=Product.Create;
153end;
154
155destructor IBMBuilder.Destroy;
156begin
157 AProduct.Free;
158 inherited Destroy;
159end;
160
161function IBMBuilder.GetComputer: Tobject;
162begin
163 result:=AProduct;
164end;
165
166{ ComputerDirector }
167
168constructor ComputerDirector.Create(ABuilder: Builder);
169begin
170 ABuilder.BuilderBoard();
171 ABuilder.BuilderCpu();
172 ABuilder.BuilderMenory()
173end;
174
175{ Product }
176
177procedure Product.Add(APart: PPart);
178begin
179 AProduct.Add(APart);
180end;
181
182constructor Product.Create;
183begin
184 AProduct:=TList.Create;
185end;
186
187destructor Product.Destroy;
188begin
189
190 AProduct.Free;
191 inherited Destroy;
192end;
193
194procedure Product.Say;
195var
196i:integer;
197begin
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
204end;
205var
206ABuilder,BBuilder:Builder;
207DELLProduct,IBMProduct:Product;
208begin
209try
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;
222end.
对于Pascal语言来说要特别注意对象的释放,因为作为Pascal可没有垃圾回收机制,我们应用了TList对象,这个对象是不会自动释放自己的。而且我们使用了指针,这也要进行释放。仔细看看程序的Destroy的运行流程,就会明白。
使用Builder模式的好处,可以让产品的组装过程同具体零件的生产分离开来,便于今后组成流程的独立演化,同时对于用户来说,他不需要知道具体的零件生产细节,他只要关心最终获得的产品就可以了。
在什么情况下需要使用建造者呢
1、 需要生成的产品对象有复杂的内部结构。
2、 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
建造者模式的效果:
1.生成器语序读者改变产品的内部表示,同时也隐藏呢产品如何组装的细节。
2.每个特定的生成器独立于其他的生成器,同时独立于程序的其他部分,这一点提高了对象的模块性,并使添加其他的生成器变得相对简单。
3.由于每个生成器是根据数据一步一步构建最终结果,所以能精确地控制生成器构建的每个结果。
生成器模式有点类似于抽象工厂模式,两者都返回由许多方法和对象组成的类,他们之间的主要差别是,抽象工厂返回的是一系列相关的类,而生成器是根据提供给它的数据一步一步地构建一个复杂的对象。