意图
提供用于创建相关或依赖对象系列的接口,而无需指定它们的具体类。
解释
真实世界的例子
要创建一个王国,我们需要具有共同主题的对象。精灵王国需要精灵国王、精灵城堡和精灵军队,而兽人王国需要兽人国王、兽人城堡和兽人军队。王国中的对象之间存在依赖关系。
简单来说
一个创建工厂的工厂;将单个但相关/依赖的工厂组合在一起而不指定它们的具体类的工厂。
维基百科说
抽象工厂模式提供了一种封装一组具有共同主题的独立工厂的方法,而无需指定它们的具体类
程序示例
翻译上面的王国例子。首先,我们为王国中的对象提供了一些接口和实现。
unit FactoryDemo_impl;
interface
uses System.SysUtils;
type
ICastle = interface
['{CB0DB3CF-F5F5-493E-B6CE-6918504B413D}']
function getDescription: String;
end;
IKing = interface
['{A1CFC1E8-5036-4060-957C-3B8792FDA5EB}']
function getDescription: String;
end;
IArmy = interface
['{DF1957AD-B6DA-4D65-B6A5-BF798407B0D2}']
function getDescription: String;
end;
IKingdomFactory = interface
['{DAFDEBA0-8ED4-4F61-ACD6-1C2199AD8DA6}']
function createCastle: ICastle;
function createKing: IKing;
function createArmy: IArmy;
end;
TElfCastle = class(TInterfacedObject, ICastle)
public
class var DESCRIPTION: String;
function getDescription: String;
end;
TElfArmy = class(TInterfacedObject, IArmy)
public
class var DESCRIPTION: String;
function getDescription: String;
end;
TElfKing = class(TInterfacedObject, IKing)
public
class var DESCRIPTION: String;
function getDescription: String;
end;
TOrcCastle = class(TInterfacedObject, ICastle)
public
class var DESCRIPTION: String;
function getDescription: String;
end;
TOrcArmy = class(TInterfacedObject, IArmy)
public
class var DESCRIPTION: String;
function getDescription: String;
end;
TOrcKing = class(TInterfacedObject, IKing)
public
class var DESCRIPTION: String;
function getDescription: String;
end;
TElfKingdomFactory = class(TInterfacedObject,IKingdomFactory)
public
function createCastle: ICastle;
function createKing: IKing;
function createArmy: IArmy ;
end;
TOrcKingdomFactory = class(TInterfacedObject, IKingdomFactory)
public
function createCastle: ICastle;
function createKing: IKing;
function createArmy: IArmy ;
end;
TKingdomType = (ELF, ORC);
TFactoryMaker = class
public
class function makeFactory(Atype: TKingdomType ): IKingdomFactory; static;
end;
implementation
class function TFactoryMaker.makeFactory(Atype: TKingdomType ): IKingdomFactory;
begin
case Atype of
ELF:
result := TElfKingdomFactory.Create;
ORC:
result := TOrcKingdomFactory.Create;
else
raise Exception.Create('KingdomType not supported.');
end;
end;
function TElfKingdomFactory.createCastle: ICastle;
begin
Result := TElfCastle.Create;
end;
function TElfKingdomFactory.createKing: IKing;
begin
result := TElfKing.Create;
end;
function TElfKingdomFactory.createArmy: IArmy;
begin
result := TElfArmy.Create;
end;
function TOrcKingdomFactory.createCastle: ICastle;
begin
Result := TOrcCastle.Create;
end;
function TOrcKingdomFactory.createKing: IKing;
begin
result := TOrcKing.Create;
end;
function TOrcKingdomFactory.createArmy: IArmy;
begin
result := TOrcArmy.Create;
end;
function TElfCastle.getDescription: String;
begin
Exit(DESCRIPTION);
end;
function TElfKing.getDescription: String;
begin
Exit(DESCRIPTION);
end;
function TElfArmy.getDescription: String;
begin
Exit(DESCRIPTION);
end;
function TOrcCastle.getDescription: String;
begin
Exit(DESCRIPTION);
end;
function TOrcKing.getDescription: String;
begin
Exit(DESCRIPTION);
end;
function TOrcArmy.getDescription: String;
begin
Exit(DESCRIPTION);
end;
initialization
TElfCastle.DESCRIPTION := 'This is the elven castle!';
TElfKing.DESCRIPTION := 'This is the elven king!';
TElfArmy.DESCRIPTION := 'This is the elven Army!';
TOrcCastle.DESCRIPTION := 'This is the orc castle!';
TOrcKing.DESCRIPTION := 'This is the orc king!';
TOrcArmy.DESCRIPTION := 'This is the orc Army!';
end.
实例化工厂,然后调用其中的方法。
try
{ TODO -oUser -cConsole Main : Insert code here }
var Factory := TFactoryMaker.makeFactory(TKingdomType.ELF);
var S := Factory.createArmy.getDescription;
Writeln(S);
Factory := TFactoryMaker.makeFactory(TKingdomType.ORC);
S := Factory.createArmy.getDescription;
Writeln(S);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;