示例:生成器接口
说明:
(1)、定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
(2)、结构
生成器
Builder:抽象生成器,为创建一个Product对象的各个部件指定抽象接口。
ConcreteBuilder:具体生成器,实现Builder的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示。提供一个检索产品的接口来取得Product(例如,GetASCIIText和GetTextWidget)。
导向器
Director:构造一个使用Builder接口的对象。
产品
Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
(3)、协作
<1>、客户创建Director对象,并用它所想要的Builder对象进行配置。
<1>、一旦产品部件被生成,导向器就会通知生成器。
<3>、生成器处理导向器的请求,并将产品部件(如Text标记)添加到该产品中。
<4>、客户从生成器中检索产品(Text文档)。
特点:
通常情况下,一个抽象的Builder类为导向者可能要求创建的每一个构件定义一个操作,这些操作缺省情况下什么都不做。一个ConcreteBuilder类对它有兴趣创建的构件重定义这些操作。
客户不需要知道产品内部用到的类的信息,这些产品内部类是不会出现在Builder接口中的。
代码:
unit uBuilder;
interface
uses
Classes;
type
TPart = class
private
FState: string;
public
property State: string read FState write FState;
end;
TPartA = class(TPart)
public
constructor Create;
end;
TPartB = class(TPart)
public
constructor Create;
end;
TPartC = class(TPart)
public
constructor Create;
end;
TPartList = class
private
FItemList: TList;
function GetCount: Integer;
function GetItems(Index: integer): TPart;
public
constructor Create;
destructor Destroy; override;
//---
procedure Clear;
function Add(const Part: TPart): integer;
//---
property Count: Integer read GetCount;
property Items[Index: integer]: TPart read GetItems;
end;
TProduct = class
private
FParts: TPartList;
function GetState: string;
public
constructor Create;
destructor Destroy; override;
//---
procedure AddPart(Part: TPart);
//---
property State: string read GetState;
end;
TBuilder = class
public
procedure BuildPartA; virtual;
procedure BuildPartB; virtual;
procedure BuildPartC; virtual;
end;
TConcreteBuilder = class(TBuilder)
private
FProduct: TProduct;
public
constructor Create;
//---
procedure BuildPartA; override;
procedure BuildPartB; override;
procedure BuildPartC; override;
//---
function GetResult: TProduct;
end;
TDirector = class
private
FBuilder: TBuilder;
public
constructor Create(Builder: TBuilder);
//---
procedure Construct;
end;
implementation
constructor TPartA.Create;
begin
self.State := 'PartA';
end;
constructor TPartB.Create;
begin
self.State := 'PartB';
end;
constructor TPartC.Create;
begin
self.State := 'PartC';
end;
constructor TPartList.Create;
begin
inherited;
//---
FItemList := TList.Create;
end;
destructor TPartList.Destroy;
begin
Clear;
FItemList.Free;
//---
inherited;
end;
function TPartList.Add(const Part: TPart): integer;
begin
if Assigned(Part) then
Result := FItemList.Add(Part)
else
Result := -1;
end;
procedure TPartList.Clear;
var
i: Integer;
begin
with FItemList do
begin
for i := 0 to Count - 1 do
TObject(Items[i]).Free;
//---
Clear;
end;
end;
function TPartList.GetCount: Integer;
begin
Result := FItemList.Count;
end;
function TPartList.GetItems(Index: integer): TPart;
begin
Result := FItemList[Index];
end;
constructor TProduct.Create;
begin
FParts := TPartList.Create;
end;
destructor TProduct.Destroy;
begin
FParts.Free;
//---
inherited;
end;
procedure TProduct.AddPart(Part: TPart);
begin
FParts.Add(Part);
end;
function TProduct.GetState: string;
var
i: integer;
begin
Result := '';
//---
with FParts do
begin
for i := 0 to Count - 1 do
Result := Result + Items[i].State + ' ';
end;
end;
procedure TBuilder.BuildPartA;
begin
end;
procedure TBuilder.BuildPartB;
begin
end;
procedure TBuilder.BuildPartC;
begin
end;
constructor TConcreteBuilder.Create;
begin
FProduct := nil;
end;
procedure TConcreteBuilder.BuildPartA;
begin
if FProduct = nil then
FProduct := TProduct.Create;
//---
FProduct.AddPart(TPartA.Create);
end;
procedure TConcreteBuilder.BuildPartB;
begin
if FProduct = nil then
FProduct := TProduct.Create;
//---
FProduct.AddPart(TPartB.Create);
end;
procedure TConcreteBuilder.BuildPartC;
begin
if FProduct = nil then
FProduct := TProduct.Create;
//---
FProduct.AddPart(TPartC.Create);
end;
function TConcreteBuilder.GetResult: TProduct;
begin
Result := FProduct;
end;
constructor TDirector.Create(Builder: TBuilder);
begin
FBuilder := Builder;
end;
procedure TDirector.Construct;
begin
with FBuilder do
begin
BuildPartA;
BuildPartB;
BuildPartC;
end;
end;
end.
procedure TForm1.Button1Click(Sender: TObject);
var
AClass: TClass;
Builder: TConcreteBuilder;
Director: TDirector;
Product: TProduct;
begin
Builder := TConcreteBuilder.Create;
Director := TDirector.Create(Builder);
//--
Director.Construct;
Product := Builder.GetResult;
showmessage(Product.State);
//---
Product.Free;
Builder.Free;
Director.Free;
end;