前面的工厂模式可以用来创建大量简单的类。但是现象一下像电脑这样一个复杂的产品。每台电脑都有很多部分组成,包括CPU,光驱,显卡,内存.......最终的电脑产品需要按一定的顺序,先安装CPU然后内存等等,在组装过程没有结束之前,电脑是无法使用的。由于这一组装过程可能很复杂,而且可能会经常变动。那么就有必要将这易变的过程抽象出一个外部电脑组装者来负责产品的组装过程。另外,客户对于电脑产品肯定会有一些偏好,比如某些人喜欢DELL电脑,有些人喜欢IBM电脑,这些电脑生产者的组装产品的方式几乎雷同,也就是说针对客户的不同需要,电脑组装者的构造过程可以适合于不同的生产者。
      对于这样的有多个零件组成的复杂产品的组装过程,就可以使用Builder建造者模式来完成。
 

建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

我们来看看其UML模型:

建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者(ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的方法:一个是建造方法如BuliderCPU,BuilderBoard等,另一个是结果返还方法GetComputer。

具体建造者(Concrete Builder)角色:担任这个角色的是于应用程序紧密相关的类,它们在应用程序调用下创建产品实例,这里为DellBuilder类,IBMBuilder类。这个角色主要完成实现Builder角色提供的接口,一步一步完成创建产品实例的过程。

指导者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。导演者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象,这里为ComputerDirector类。

我们来看看其代码实现(C#):
  1using System;
  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
下面的代码为实现同样的功能的Pascal代码:
  1program 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
 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.由于每个生成器是根据数据一步一步构建最终结果,所以能精确地控制生成器构建的每个结果。
生成器模式有点类似于抽象工厂模式,两者都返回由许多方法和对象组成的类,他们之间的主要差别是,抽象工厂返回的是一系列相关的类,而生成器是根据提供给它的数据一步一步地构建一个复杂的对象。


   
posted on 2006-04-28 17:52  coffeeliu  阅读(774)  评论(0编辑  收藏  举报