Если честно, то я, наверное, до конца так и не понял, в чем различие между этими шаблонами. Оба предназначены для создания групп объектов, которые имеют общее поведение (было бы странно если бы они имели разное реализуя общий интерфейс). Хотя естественно, что если мы наследуем просто от класса с абстрактными методами, то в классе потомке можно добавить новые уникальные методы, чего не сделаешь с классами, которые наследуются от TInterfacedObject.
Реализация Abstract Factory (в наглую сдерта с вики + небольшие правки)
unit AbstractFactory; interface type // AbstractProduct TCar = class public function Info: string; virtual; abstract; end; // ConcreteProductA TFord = class(TCar) public procedure Test; function Info: string; override; end; // ConcreteProductB TToyota = class(TCar) public function Info: string; override; end; // AbstractFactory TCarFactory = class public function CreateCar: TCar; virtual; abstract; end; // ConcreteFactoryA TFordFactory = Class(TCarFactory) public function CreateCar: TCar; override; end; // ConcreteFactoryB TToyotaFactory = Class(TCarFactory) public function CreateCar: TCar; override; end; implementation { TFord } function TFord.Info: string; begin Result:='Ford'; end; procedure TFord.Test; begin Writeln('TFord.Test'); end; { TToyota } function TToyota.Info: string; begin Result:='Toyota'; end; { TFordFactory } function TFordFactory.CreateCar: TCar; begin Result := TFord.Create; end; { TToyotaFactory } function TToyotaFactory.CreateCar: TCar; begin Result := TToyota.Create; end; end.
Реализация FactoryMethod
unit FactoryMethod; interface type // "Product" IProduct = interface procedure GetName; end; // "ConcreteProductA" TConcreteProductA = class(TInterfacedObject, IProduct) procedure GetName; end; // "ConcreteProductB" TConcreteProductB = class(TInterfacedObject, IProduct) procedure GetName; end; // "Creator" ICreator = interface function FactoryMethod: IProduct; end; // "ConcreteCreatorA" TConcreteCreatorA = class(TInterfacedObject, ICreator) function FactoryMethod: IProduct; end; // "ConcreteCreatorB" TConcreteCreatorB = class(TInterfacedObject, ICreator) function FactoryMethod: IProduct; end; implementation { TConcreteCreatorA } function TConcreteCreatorA.FactoryMethod: IProduct; begin Result := TConcreteProductA.Create; end; { TConcreteCreatorB } function TConcreteCreatorB.FactoryMethod: IProduct; begin Result := TConcreteProductB.Create; end; { TConcreteProductA } procedure TConcreteProductA.GetName; begin Writeln('TConcreteProductA.GetName;'); end; { TConcreteProductB } procedure TConcreteProductB.GetName; begin Writeln('TConcreteProductB.GetName;'); end; end.
Builder.
Позволяет сконструировать сложный объект на основе “кирпичиков” – более простых объектов. Выходит, что мы можем иметь два объекта одного типа, но с разным содержимым.
Реализация
unit Builder; interface uses SysUtils, Classes; type // Product TProduct = class private FParts: TStringList; public procedure Add(Part: string); procedure Show; constructor Create; destructor Destroy; end; // Builder IBuilder = interface['{52A37564-3B0B-4A5A-ADF0-1DD7AB3A6789}'] procedure BuildPartA; procedure BuildPartB; function GetResult: TProduct; end; // ConcreteBuilder1 TConcreteBuilder1 = class(TInterfacedObject, IBuilder) private FProduct: TProduct; public procedure BuildPartA; procedure BuildPartB; function GetResult: TProduct; constructor Create; destructor Destroy; end; // ConcreteBuilder2 TConcreteBuilder2 = class(TInterfacedObject, IBuilder) private FProduct: TProduct; public procedure BuildPartA; procedure BuildPartB; function GetResult: TProduct; constructor Create; destructor Destroy; end; TDirector = class public procedure Construct(Builder: IBuilder); end; implementation { Product } procedure TProduct.Add(Part: string); begin FParts.Add(Part); end; constructor TProduct.Create; begin FParts := TStringList.Create; end; destructor TProduct.Destroy; begin FreeAndNil(FParts); end; procedure TProduct.Show; var I: Integer; begin Writeln('Product Parts -------'); for I := 0 to FParts.Count - 1 do Writeln(FParts[I]); end; { TConcreteBuilder1 } procedure TConcreteBuilder1.BuildPartA; begin FProduct.Add('PatrA'); FProduct.Add('PatrB'); FProduct.Add('PatrC'); end; procedure TConcreteBuilder1.BuildPartB; begin FProduct.Add('PatrD'); end; constructor TConcreteBuilder1.Create; begin FProduct := TProduct.Create; end; destructor TConcreteBuilder1.Destroy; begin FreeAndNil(FProduct); end; function TConcreteBuilder1.GetResult: TProduct; begin Result := FProduct; end; { TConcreteBuilder2 } procedure TConcreteBuilder2.BuildPartA; begin FProduct.Add('PatrX'); end; procedure TConcreteBuilder2.BuildPartB; begin FProduct.Add('PatrY'); end; constructor TConcreteBuilder2.Create; begin FProduct := TProduct.Create; end; destructor TConcreteBuilder2.Destroy; begin FreeAndNil(FProduct); end; function TConcreteBuilder2.GetResult: TProduct; begin Result := FProduct; end; { TDirector } procedure TDirector.Construct(Builder: IBuilder); begin Builder.BuildPartA(); Builder.BuildPartB(); end; end.
Пример использования
var //Builder Director: TDirector; B1, B2: IBuilder; P1, P2: TProduct; begin Director := TDirector.Create; B1 := TConcreteBuilder1.Create; Director.Construct(B1); P1 := B1.GetResult; P1.Show; B2 := TConcreteBuilder2.Create; Director.Construct(B2); P2 := B2.GetResult; P2.Show; end;
Комментариев нет:
Отправить комментарий