意图:抽象工厂用于创建一组或一系列相关的对象并提供一个统一的接口。
优点:很容易就能扩展一组对象,只需继承抽象工厂即可。
缺点:若想增加抽象产品就要修改抽象工厂的接口了。
用QQ农场中购买饰品的例子可以很好的理解抽象工厂模式,如图:

背景、房子、狗窝、栅栏就是抽象工厂中的抽象产品。示意代码:
下面是抽象产品:

代码
1
{抽象背景}
2
3
unit uBackground;
4
5
interface
6
7
type
8
TBackground = class(TObject)
9
public
10
procedure Buy; virtual; abstract;
11
end;
12
13
implementation
14
15
end.
其它抽象产品代码略。
下面是抽象工厂,‘创建了’一组相关的抽象产品:

代码
1
unit uAbstractFacilitiesFactory;
2
3
interface
4
5
uses
6
uBackground, uHouse, uKennel, uFence;
7
8
type
9
TAbstractFacilitiesFactory = class(TObject)
10
public
11
function CreateBackground: TBackground; virtual; abstract;
12
function CreateHouse: THouse; virtual; abstract;
13
function CreateKennel: TKennel; virtual; abstract;
14
function CreateFence: TFence; virtual; abstract;
15
end;
16
17
implementation
18
19
end.
此时若想得到蒙古包系列的背景、房子、狗窝、栅栏,先从抽象的背景、房子、狗窝、栅栏扩展出相应的蒙古包系列的产品。
下面是蒙古包系列的背景:

代码
1
unit uYurtSeriesBackground;
2
3
interface
4
5
uses
6
uBackground;
7
8
type
9
TYurtSeriesBackground = class(TBackground)
10
public
11
procedure Buy; override;
12
end;
13
14
implementation
15
16
{ TYurtSeriesBackground }
17
18
procedure TYurtSeriesBackground.Buy;
19
begin
20
inherited;
21
Writeln('购买蒙古包系列的背景 (', Self.ClassName, ')');
22
end;
23
24
end.
蒙古包系列的其他产品代码略。
然后从抽象工厂继承一个用于创建蒙古包系列产品的具体工厂:

代码
1
unit uYurtSeriesFactory;
2
3
interface
4
5
uses
6
uAbstractFacilitiesFactory, uBackground, uHouse, uKennel, uFence,
7
uYurtSeriesBackground, uYurtSeriesFence, uYurtSeriesHouse, uYurtSeriesKennel;
8
9
type
10
TYurtSeriesFactory = class(TAbstractFacilitiesFactory)
11
public
12
function CreateBackground: TBackground; override;
13
function CreateHouse: THouse; override;
14
function CreateKennel: TKennel; override;
15
function CreateFence: TFence; override;
16
end;
17
18
implementation
19
20
{ TYurtSeriesFactory }
21
22
function TYurtSeriesFactory.CreateBackground: TBackground;
23
begin
24
Result := TYurtSeriesBackground.Create;
25
end;
26
27
function TYurtSeriesFactory.CreateFence: TFence;
28
begin
29
Result := TYurtSeriesFence.Create;
30
end;
31
32
function TYurtSeriesFactory.CreateHouse: THouse;
33
begin
34
Result := TYurtSeriesHouse.Create;
35
end;
36
37
function TYurtSeriesFactory.CreateKennel: TKennel;
38
begin
39
Result := TYurtSeriesKennel.Create;
40
end;
41
42
end.
至此,蒙古包系列的背景、房子、狗窝、栅栏创建完毕。风车系列的创建同蒙古包系列,代码省略。
如果还有其他系列的产品,比如糖果系列、地中海情趣系列,方法也是一样的。但是如果要增加一个与背景、房子、狗窝、栅栏同级的抽象产品就要修改抽象工厂的接口了。
最后,做一个简单的测试:

代码
1
unit uTest;
2
3
interface
4
5
uses
6
SysUtils, uAbstractFacilitiesFactory, uBackground, uFence, uHouse, uKennel;
7
8
type
9
TTest = class(TObject)
10
public
11
procedure BuyFacilities(aFactory: TAbstractFacilitiesFactory);
12
end;
13
14
implementation
15
16
{ TTestFactory }
17
18
procedure TTest.BuyFacilities(aFactory: TAbstractFacilitiesFactory);
19
var
20
aBackground: TBackground;
21
aHouse: THouse;
22
aKennel: TKennel;
23
aFence: TFence;
24
begin
25
try
26
aBackground := aFactory.CreateBackground;
27
aHouse := aFactory.CreateHouse;
28
aKennel := aFactory.CreateKennel;
29
aFence := aFactory.CreateFence;
30
31
aBackground.Buy;
32
aHouse.Buy;
33
aKennel.Buy;
34
aFence.Buy;
35
finally
36
FreeAndNil(aBackground);
37
FreeAndNil(aHouse);
38
FreeAndNil(aKennel);
39
FreeAndNil(aFence);
40
end;
41
end;
42
43
end.

代码
1
program pQQFarm;
2
3
{$APPTYPE CONSOLE}
4
5
uses
6
SysUtils,
7
uAbstractFacilitiesFactory in 'AbstractFactory\uAbstractFacilitiesFactory.pas',
8
uBackground in 'AbstractFactory\uBackground.pas',
9
uFence in 'AbstractFactory\uFence.pas',
10
uHouse in 'AbstractFactory\uHouse.pas',
11
uKennel in 'AbstractFactory\uKennel.pas',
12
uYurtSeriesFactory in 'YurtSeriesFactory\uYurtSeriesFactory.pas',
13
uYurtSeriesBackground in 'YurtSeriesFactory\uYurtSeriesBackground.pas',
14
uYurtSeriesHouse in 'YurtSeriesFactory\uYurtSeriesHouse.pas',
15
uYurtSeriesKennel in 'YurtSeriesFactory\uYurtSeriesKennel.pas',
16
uYurtSeriesFence in 'YurtSeriesFactory\uYurtSeriesFence.pas',
17
uWildmillSeriseFactory in 'WildmillSeriseFactory\uWildmillSeriseFactory.pas',
18
uWildmillSeriseBackground in 'WildmillSeriseFactory\uWildmillSeriseBackground.pas',
19
uWildmillSeriseHouse in 'WildmillSeriseFactory\uWildmillSeriseHouse.pas',
20
uWildmillSeriseKennel in 'WildmillSeriseFactory\uWildmillSeriseKennel.pas',
21
uWildmillSeriseFence in 'WildmillSeriseFactory\uWildmillSeriseFence.pas',
22
uTest in 'uTest.pas';
23
24
var
25
aFactory: TAbstractFacilitiesFactory;
26
aTest: TTest;
27
28
begin
29
try
30
{若想买到蒙古包系列的背景、房子、狗窝、栅栏,恢复本句,注释掉下一句。}
31
//aFactory := TYurtSeriesFactory.Create;
32
aFactory := TWildmillSeriseFactory.Create;
33
34
aTest := TTest.Create;
35
36
aTest.BuyFacilities(aFactory);
37
finally
38
FreeAndNil(aFactory);
39
FreeAndNil(aTest);
40
end;
41
42
Readln;
43
end.
测试结果:
