设计模式的目的就是尽量减少“变化”对程序的影响,尤其是对客户程序的影响。AbstractFactory模式作为创建型模式的一种,解决的就是“new”在变化中可能引起的问题。
先来看看new有何种不好,举个创建汽车的车门的例子:
很自然的一种想法是:Door *door = new Door();
但是如果遇到创建老爷车的车门,创建现代车的车门,这段代码就无所适从了。
OO为我们提供了哪些精华的思想?“封装”,是的,将车门的创建封装起来,于是我们有了静态工厂方法:
客户程序代码:
1
Door* door = doorFactory->CreateDoor();
库程序代码:
1
class DoorFactory
2

{
3
public:
4
Door* CreateDoor()
5
{
6
return new Door();
7
}
8
}
客户程序在此是不会变化的,不管你是老爷车门,现代车门,还是钻石车门,这些和客户程序代码都是没关系的,究竟CreateDoor出来如何结果都交给多态来判断,我们不用操心。
但是库程序代码还是需要更改的,但我们已经将“变化”与客户程序隔离了。
需求又有变化了,不光要创建车门,还需要创建引擎,车灯,而且还是不同风格的。
这时候静态工厂已经应付不来了,静态工厂有其自身的缺陷“不能应对不同系列对象”的变化。
动机:
软件系统中,经常面临“一系列相互依赖的对象”的创建工作。(两个特征:“一系列”,“相互依赖”)
将创建过程封装起来,避免“客户程序”和“多系列具体对象的创建工作”的紧耦合。
意图:
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定他们具体的类。(GoF23)
思路:

对于客户程序来说,只依赖于三个抽象的类:AbstractFactory,AbstractProductA,AbstractProductB。
以下是客户程序代码:
1
class CarManager
2

{
3
protected:
4
AbstractFactory *abstractFactory;
5
public:
6
//创造Car
7
void createCar(AbstractFactory *abstractFactory)
8
{
9
abstractFactory->CreateEngine();
10
abstractFactory->CreateDoor();
11
abstractFactory->CreateLight();
12
}
13
//其他的操作

14
void run()
{}
15
};
16
17
int _tmain(int argc, _TCHAR* argv[])
18

{
19
CarManager *carManager = new CarManager();
20
//创建Classic风格的汽车
21
carManager->createCar(new ClassicFactory());
22
23
return 0;
24
}
所有关于创建的操作都是用抽象类完成的,对于具体是何种类型的对象由多态实现,以此来使“客户代码”和“多系列具体对象的创建工作”达到松耦合。
如果遇到还需要扩展其他风格的汽车,可以按下图的思路

红色的部分对应新风格的车辆,只需在库程序中添加ConcreteFactory3,ProductA3,ProductB3三个类,而对于客户代码CarManager来说完全不受影响。
总结:
AbstractFactory模式有以下三个要点:
1.应对的问题是“多风格的系列对象创建”的变化问题,“系列对象”指的是这些对象之间有相互依赖或者相互作用的关系。否则使用“静态工厂”足以。
2.抽象工厂和静态工厂的核心是“封装”,将对象的创建进行封装,避免“new”引起的问题
3.抽象工程的另一个核心是“多态”,通过动态绑定来处理“不同风格”的问题
注:
AbstractFactory模式主要针对“风格”的变化,如果“对象”本身经常变化,那么该模式并不适用。
自己做的示例代码,仅供参考
1
/**/////////////////////////////////////////////////////////////////////////// 2
// AbstractFactoryTest for AbstractFactory Pattern Test
3
//
4
/**/////////////////////////////////////////////////////////////////////////// 5
6
#include "stdafx.h"
7
#include "iostream"
8
using namespace std;
9
10
//Engine,Door,Light are the Abstract Product
11
//这三个类对应UML图中的AbstractProduct类
12
class Engine
13

{
14
public:
15
Engine()
16
{
17
cout<<"Abstract Engine Create"<<endl;
18
}
19
virtual void doSomething() = 0;
20
};
21
22
class Door
23

{
24
public:
25
Door()
26
{
27
cout<<"Abstract Door Create"<<endl;
28
}
29
virtual void doSomething() = 0;
30
};
31
32
class Light
33

{
34
public:
35
Light()
36
{
37
cout<<"Abstract Light Create"<<endl;
38
}
39
virtual void doSomething() = 0;
40
};
41
42
//Abstract Factory
43
class AbstractFactory
44

{
45
public:
46
AbstractFactory()
47
{
48
cout<<"AbstractFactory Create"<<endl;
49
}
50
virtual Engine* CreateEngine() = 0;
51
virtual Door* CreateDoor() = 0;
52
virtual Light* CreateLight() = 0;
53
};
54
55
//SpeedEngine,SpeedDoor,SpeedLight are the Products of Speed Style
56
//这三个类对应UML图中的ProductA1,ProductB1,ProductC1类
57
class SpeedEngine:public Engine
58

{
59
public :
60
SpeedEngine()
61
{
62
cout<<"Speed Engine Create"<<endl;
63
}
64
void doSomething()
{ }
65
};
66
67
class SpeedDoor:public Door
68

{
69
public :
70
SpeedDoor()
71
{
72
cout<<"Speed Door Create"<<endl;
73
}
74
void doSomething()
{ }
75
};
76
77
class SpeedLight:public Light
78

{
79
public :
80
SpeedLight()
81
{
82
cout<<"Speed Light Create"<<endl;
83
}
84
void doSomething()
{ }
85
};
86
87
//classicEngine,classicDoor,classicLight are the products of Classic style
88
//这三个类对应UML图中的ProductA2,ProductB2,ProductC2类
89
class ClassicEngine:public Engine
90

{
91
public :
92
ClassicEngine()
93
{
94
cout<<"Classic Engine Create"<<endl;
95
}
96
void doSomething()
{ }
97
};
98
99
class ClassicDoor:public Door
100

{
101
public :
102
ClassicDoor()
103
{
104
cout<<"Classic Door Create"<<endl;
105
}
106
void doSomething()
{ }
107
};
108
109
class ClassicLight:public Light
110

{
111
public :
112
ClassicLight()
113
{
114
cout<<"Classic Light Create"<<endl;
115
}
116
void doSomething()
{ }
117
};
118
119
//Factory for Speed Cars
120
//对应UML图中的ConcreteFactory1类
121
class SpeedFactory:public AbstractFactory
122

{
123
public:
124
SpeedFactory()
125
{
126
cout<<"SpeedFactory Create"<<endl;
127
}
128
virtual Engine* CreateEngine()
129
{
130
return new SpeedEngine();
131
}
132
virtual Door* CreateDoor()
133
{
134
return new SpeedDoor();
135
}
136
virtual Light* CreateLight()
137
{
138
return new SpeedLight();
139
}
140
};
141
142
//Factory for classic Cars
143
//对应UML图中的ConcreteFactory2类
144
class ClassicFactory:public AbstractFactory
145

{
146
public:
147
ClassicFactory()
148
{
149
cout<<"ClassicFactory Create"<<endl;
150
}
151
virtual Engine* CreateEngine()
152
{
153
return new ClassicEngine();
154
}
155
virtual Door* CreateDoor()
156
{
157
return new ClassicDoor();
158
}
159
virtual Light* CreateLight()
160
{
161
return new ClassicLight();
162
}
163
};
164
165
//Client Code ---- use the Abstract Factory & Abstract Product to create the car
166
//this is never changed
167
class CarManager
168

{
169
protected:
170
AbstractFactory *abstractFactory;
171
public:
172
//创造Car
173
void createCar(AbstractFactory *abstractFactory)
174
{
175
abstractFactory->CreateEngine();
176
abstractFactory->CreateDoor();
177
abstractFactory->CreateLight();
178
}
179
//其他的操作

180
void run()
{}
181
};
182
183
int _tmain(int argc, _TCHAR* argv[])
184

{
185
CarManager *carManager = new CarManager();
186
//创建Classic风格的汽车
187
carManager->createCar(new ClassicFactory());
188
189
return 0;
190
}