建造模式(Builder)
作者 陈省
前面的工厂模式可以用来创建大量的简单类,但是想像一下像电脑这样一个复杂的产品,每台电脑都由很多部分而成,包括CPU,硬盘,光驱,显卡,内存,键盘,鼠标,主板等等部分构成,最终的电脑产品需要按照一定的顺序,先装主板,再装CPU,然后内存…的顺序来组装而成,在组装过程没有结束前,电脑是无法使用的。由于这一组装过程可能很复杂,而且可能会经常变动。那么就有必要将这易变的过程抽象出一个外部电脑主张者来负责产品的组装过程。
另外,客户对于电脑产品肯定会有一些偏好,比如某些人喜欢联想电脑,有些人喜欢宏基电脑,这些电脑生产者的组装产品的方式几乎雷同,那么也就是说针对客户的不同需要,电脑组装者的构造过程可以适用于不同的生产者。
那么对于这样的有多个零件组成的复杂产品的组装过程,就可以使用Builder构建者模式来完成,它的UML模型图如下图所示意:
在Builder模式中,生产产品的类TAbstractBuilder是一个抽象类,它定义了生产具体零部件和获得最终产品的接口,其中BuildXXX方法是生产CPU,主板等零件方法,而GetComputer是返回组装完毕的产品的方法。从TAbstractBuilder类派生的两个类TLegendBuilder和TAcerBuilder,分别代表实现了虚类方法的生产电脑的联想和宏基创建者类,他们负责具体产品的生产。而负责组装电脑的人叫做TComputerDirector,它负责按照一定的复杂顺序调用具体厂商的生产零件的命令,并获得最终的产品。下面是Builder模式的示意性代码:
type
TAbstractBuilder=class(TObject)
public
procedure BuildCpu();virtual;abstract;
procedure BuildBoard();virtual;abstract;
procedure BuildMemory();virtual;abstract;
//...
function GetComputer:TObject;virtual;abstract;
end;
TLegendBuilder=class(TAbstractBuilder)
public
procedure BuildCpu();override;
procedure BuildBoard();override;
procedure BuildMemory();override;
//...
function GetComputer:TObject;override;
end;
TAcerBuilder=class(TAbstractBuilder)
public
procedure BuildCpu();override;
procedure BuildBoard();override;
procedure BuildMemory();override;
//...
function GetComputer:TObject;override;
end;
TComputerDirector=class(TObject)
public
constructor Create(ABuilder:TAbstractBuilder);
end;
implementation
{ TComputerDirector }
constructor TComputerDirector.Create(ABuilder: TAbstractBuilder);
begin
ABuilder.BuildBoard();
ABuilder.BuildCpu();
ABuilder.BuildMemory();
end;
使用Builder模式创建电脑的交互图如下:
生产者首先确定自己想要的电脑品牌,然后告诉电脑组装者,电脑组装者则让具体的厂商按照指定的顺序进行生产,最后生产结束后,用户从厂商那里拿到最终的产品。生产过程的示意代码如下:
var
ABuilder:TAbstractBuilder;
ADirector:TComputerDirector;
begin
ABuilder:=TLegendBuilder.Create();
ADirector:=TComputerDirector.Create(ABuilder);
Result:=ABuilder.GetComputer();
//…
end;
使用Builder模式的好处,可以将让产品的组装过程同具体的零件的生产分离开来,同时便于今后组成流程的独立演化,同时对于用户来说,他不需要知道具体的零件生产细节,他只要关心最终获得的产品就可以了。