抽象工厂的好处在于用户可根据不同的配置调用具体的工厂对象,从而获取不同的产品。
在设计时,实现产品创建和客户端的分离。客户端通过抽象接口获取所要的产品。使用反射的方法可使工厂方法变得更加灵活。
PS:相关源码参考大话设计模式C#版本。
{*------------------------------------------------------------------------------
设计模式之抽象工厂
@author genispan
@version
@todo
@comment Delphi版抽象工厂模式
-------------------------------------------------------------------------------}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TUser = class
private
{ Private declarations }
FID:Integer;
FName:string;
public
{ Public declarations }
property ID:Integer read FID write FID;
property Name:string read FName write FName;
end;
IUser = interface
procedure Insert(AUser:TUser);
function Get(ID:Integer):TUser;
end;
TCommonUser = class(TInterfacedPersistent,IUser)
procedure Insert(AUser:TUser); virtual;abstract;
function Get(ID:Integer):TUser; virtual;abstract;
end;
TSqlServerUser= class(TCommonUser)
procedure Insert(AUser:TUser); override;
function Get(ID:Integer):TUser; override;
end;
TOracleUser= class(TCommonUser)
procedure Insert(AUser:TUser); override;
function Get(ID:Integer):TUser; override;
end;
TDepartment = class
private
{ Private declarations }
FDeptID:Integer;
FDeptName:string;
public
{ Public declarations }
property DeptID:Integer read FDeptID write FDeptID;
property DeptName:string read FDeptName write FDeptName;
end;
IDepartment = interface
procedure InsertDept(ADpt:TDepartment);
function GetDept(DeptID:Integer):TDepartment;
end;
TCommonDept = class(TInterfacedPersistent,IDepartment)
procedure InsertDept(ADept:TDepartment); virtual;abstract;
function GetDept(DeptID:Integer):TDepartment;virtual;abstract;
end;
TSqlServerDepartment= class(TCommonDept)
procedure InsertDept(ADept:TDepartment); override;
function GetDept(DeptID:Integer):TDepartment; override;
end;
TOracleDepartment= class(TCommonDept)
procedure InsertDept(ADept:TDepartment); override;
function GetDept(DeptID:Integer):TDepartment; override;
end;
IFactory = interface
function CreateUser:IUser;
function CreateDpt:IDepartment;
end;
TFactory = class(TInterfacedObject,IFactory)
private
{ Private declarations }
public
{ Public declarations }
function CreateUser:IUser;
function CreateDpt:IDepartment;
end;
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
FDBType:string;
implementation
{$R *.dfm}
{TSqlServerUser}
procedure TSqlServerUser.Insert(AUser:TUser);
begin
Form1.Memo1.Lines.Add('SqlServer用户表增加一条记录!');
end;
function TSqlServerUser.Get(ID:Integer):TUser;
begin
Form1.Memo1.Lines.Add(Format('SqlServer获取用户【%d】记录!',[ID]));
Result:=nil;
end;
{TOracleUser}
procedure TOracleUser.Insert(AUser:TUser);
begin
Form1.Memo1.Lines.Add('Oracle用户表增加一条记录!');
end;
function TOracleUser.Get(ID:Integer):TUser;
begin
Form1.Memo1.Lines.Add(Format('Oracle获取用户【%d】记录!',[ID]));
Result:=nil;
end;
{TSqlServerDepartment}
procedure TSqlServerDepartment.InsertDept(ADept:TDepartment);
begin
Form1.Memo1.Lines.Add('SqlServere部门表增加一条记录!');
end;
function TSqlServerDepartment.GetDept(DeptID:Integer):TDepartment;
begin
Form1.Memo1.Lines.Add(Format('SqlServer获取部门【%d】记录!',[DeptID]));
Result:=nil;
end;
{TOracleDepartment}
procedure TOracleDepartment.InsertDept(ADept:TDepartment);
begin
Form1.Memo1.Lines.Add('Oracle部门表增加一条记录!');
end;
function TOracleDepartment.GetDept(DeptID:Integer):TDepartment;
begin
Form1.Memo1.Lines.Add(Format('Oracle获取用户【%d】记录!',[DeptID]));
Result:=nil;
end;
{TFactory}
function TFactory.CreateUser:IUser;
begin
Result:= IUser(TCommonUser(FindClass('T'+FDBType+'User').Create));
end;
function TFactory.CreateDpt:IDepartment;
begin
Result:= IDepartment(TCommonDept(FindClass('T'+FDBType+'Department').Create));
end;
{TForm1}
procedure TForm1.Button1Click(Sender: TObject);
var
vUser:TUser;
vDept:TDepartment;
interfaceUser:IUser;
interfaceDept:IDepartment;
vFactory:TFactory;
begin
FDBType := 'Oracle';
vUser := TUser.Create;
vDept := TDepartment.Create;
vFactory:=TFactory.Create;
interfaceUser := vFactory.CreateUser;
interfaceUser.Insert(vUser);
interfaceUser.Get(1);
interfaceDept := vFactory.CreateDpt;
interfaceDept.InsertDept(vDept);
interfaceDept.GetDept(1);
end;
initialization
RegisterClasses([TSqlServerUser,TOracleUser,TSqlServerDepartment,TOracleDepartment]);
end.