意图:抽象工厂用于创建一组或一系列相关的对象并提供一个统一的接口。
优点:很容易就能扩展一组对象,只需继承抽象工厂即可。
缺点:若想增加抽象产品就要修改抽象工厂的接口了。
用QQ农场中购买饰品的例子可以很好的理解抽象工厂模式,如图:
背景、房子、狗窝、栅栏就是抽象工厂中的抽象产品。示意代码:
下面是抽象产品:
代码
1{抽象背景}
2
3unit uBackground;
4
5interface
6
7type
8 TBackground = class(TObject)
9 public
10 procedure Buy; virtual; abstract;
11 end;
12
13implementation
14
15end.
其它抽象产品代码略。
下面是抽象工厂,‘创建了’一组相关的抽象产品:
代码
1unit uAbstractFacilitiesFactory;
2
3interface
4
5uses
6 uBackground, uHouse, uKennel, uFence;
7
8type
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
17implementation
18
19end.
此时若想得到蒙古包系列的背景、房子、狗窝、栅栏,先从抽象的背景、房子、狗窝、栅栏扩展出相应的蒙古包系列的产品。
下面是蒙古包系列的背景:
代码
1unit uYurtSeriesBackground;
2
3interface
4
5uses
6 uBackground;
7
8type
9 TYurtSeriesBackground = class(TBackground)
10 public
11 procedure Buy; override;
12 end;
13
14implementation
15
16{ TYurtSeriesBackground }
17
18procedure TYurtSeriesBackground.Buy;
19begin
20 inherited;
21 Writeln('购买蒙古包系列的背景 (', Self.ClassName, ')');
22end;
23
24end.
蒙古包系列的其他产品代码略。
然后从抽象工厂继承一个用于创建蒙古包系列产品的具体工厂:
代码
1unit uYurtSeriesFactory;
2
3interface
4
5uses
6 uAbstractFacilitiesFactory, uBackground, uHouse, uKennel, uFence,
7 uYurtSeriesBackground, uYurtSeriesFence, uYurtSeriesHouse, uYurtSeriesKennel;
8
9type
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
18implementation
19
20{ TYurtSeriesFactory }
21
22function TYurtSeriesFactory.CreateBackground: TBackground;
23begin
24 Result := TYurtSeriesBackground.Create;
25end;
26
27function TYurtSeriesFactory.CreateFence: TFence;
28begin
29 Result := TYurtSeriesFence.Create;
30end;
31
32function TYurtSeriesFactory.CreateHouse: THouse;
33begin
34 Result := TYurtSeriesHouse.Create;
35end;
36
37function TYurtSeriesFactory.CreateKennel: TKennel;
38begin
39 Result := TYurtSeriesKennel.Create;
40end;
41
42end.
至此,蒙古包系列的背景、房子、狗窝、栅栏创建完毕。风车系列的创建同蒙古包系列,代码省略。
如果还有其他系列的产品,比如糖果系列、地中海情趣系列,方法也是一样的。但是如果要增加一个与背景、房子、狗窝、栅栏同级的抽象产品就要修改抽象工厂的接口了。
最后,做一个简单的测试:
代码
1unit uTest;
2
3interface
4
5uses
6 SysUtils, uAbstractFacilitiesFactory, uBackground, uFence, uHouse, uKennel;
7
8type
9 TTest = class(TObject)
10 public
11 procedure BuyFacilities(aFactory: TAbstractFacilitiesFactory);
12 end;
13
14implementation
15
16{ TTestFactory }
17
18procedure TTest.BuyFacilities(aFactory: TAbstractFacilitiesFactory);
19var
20 aBackground: TBackground;
21 aHouse: THouse;
22 aKennel: TKennel;
23 aFence: TFence;
24begin
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;
41end;
42
43end.
代码
1program pQQFarm;
2
3{$APPTYPE CONSOLE}
4
5uses
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
24var
25 aFactory: TAbstractFacilitiesFactory;
26 aTest: TTest;
27
28begin
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;
43end.
测试结果: