上回讲了
Simple Factory
和
Factory Method
。简单回顾一下:
Factory Method
只能生产“一维”层次的,横向产品。也就是说,工厂生产的东东都是一类产品,都是由同一个父类派生的子类的对象。比如上次举例说到的,不管是
Nokia
的还是
Motorola
的,生产的都是手机,产品都是从
Mobile
派生出来的。
如果要想纵向的生产产品,比如,生产一个基站(这个东西好像大了点,但是偶实在想不出更好的产品了),
Factory Method
恐怕就不够用了。
各位看官请注意了,下面隆重介绍
Abstract Factory
!
1,
功能:
《设计模式》中的定义是“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类”。所谓一系列,就说明他们不都是一个父类派生出来的,但是这些对象是为了以后的应用,或者整体应用所提供的。他们之间多少有些相关或者相互依赖。
2,
基本思想:
Factory Method
可以理解为同一种产品的不同具体产品的工厂的抽象。每个具体的工厂生产出来的东东都是同一种产品(同一个父类)。
Abstract Factory
是对不用种产品(但存在一定联系)的具体产品的工厂的抽象。每个具体工厂生产出来的东东不是同一种产品(不同的父类),但有一定联系(比如同一个厂家的产品,或者同一个窗口的组件)。
3,
适用情况:
一个系统要独立于它的产品的创建、组合和表示时;
一个系统要有多个产品系列中的一个来配置时;
需要强调一系列相关的产品对象的设计以便进行联合使用时;
当要提供一个产品类库,而只想显示它们的接口而不是实现时。
4,
案例举例:
实现在不同窗口系统之间的可移动性,比如
Windows
操作系统中抽象工厂创建
Windows
下的窗口组件,
Linux
创建
Linux
的窗口组件,等等。
5,
结构:
6
,代码示例:还是用
Nokia
和
Moto
两大通信公司的
case
来说明一下:
A.
Nokia
和
Moto
两个公司都生产手机
class
MobilePhone
{
public
:
virtual
void
call() {cout
<<
"
Calling
"
<<
endl; }
//
打电话
virtual
void
shortMsg() {cout
<<
"
Short Message
"
<<
endl;};
//
收发短信
};
class
NokiaPhone :
public
MobilePhone
{
virtual
void
call() { cout
<<
"
Nokia calling
"
<<
endl; }
virtual
void
shortMsg() { cout
<<
"
Nokia short message
"
<<
endl; }
};
class
MotoPhone :
public
MobilePhone
{
virtual
void
call() { cout
<<
"
Moto calling
"
<<
endl; }
virtual
void
shortMsg() { cout
<<
"
Moto short message
"
<<
endl; }
};
B
.
Nokia
和
Moto
两个公司都生产基站系统
class
BaseStation
{
public
:
virtual
void
BTSControl() {cout
<<
"
Controlling BTS
"
<<
endl;}
virtual
void
BSCControl() {cout
<<
"
Controlling BSC
"
<<
endl;}
};
class
NokiaBaseStation :
public
BaseStation
{
public
:
void
BTSControl() {cout
<<
"
Nokia BTS control
"
<<
endl;}
void
BSCControl() {cout
<<
"
Nokia BSC control
"
<<
endl;}
};
class
MotoBaseStation :
public
BaseStation
{
public
:
void
BTSControl() {cout
<<
"
Moto BTS control
"
<<
endl;}
void
BSCControl() {cout
<<
"
Moto BSC control
"
<<
endl;}
};
C.抽象的工厂提供了标准的、生产所有不同种类产品(手机、基站)的接口。不同系列的产品由该系列的工厂生产。
Nokia
的手机和基站系统由
Nokia
的工厂生产,
Motorola
的手机和基站系统由
Motorola
公司生产。
class
Factory
{
public
:
virtual MobilePhone
*
CreatePhone()
=
NULL;
virtual
void
DestroyPhone(MobilePhone
*
p) {
if
(p) delete p;};
virtual BaseStation
*
CreateBaseStation()
=
NULL;
virtual
void
DestroyBaseStation(BaseStation
*
b) {
if
(b) delete b;};
};
class
NokiaFactory :
public
Factory
{
public
:
MobilePhone
*
CreatePhone() {
return
(
new
NokiaPhone());}
BaseStation
*
CreateBaseStation() {
return
(
new
NokiaBaseStation());}
};
class
MotoFactory :
public
Factory
{
MobilePhone
*
CreatePhone() {
return
(
new
MotoPhone());}
BaseStation
*
CreateBaseStation() {
return
(
new
MotoBaseStation());}
};
D
.下面客户端利用
Factory
创建不同系列的工厂对象,再利用这些工厂对象来创建对应系列的产品。
int
main()
{
Factory
*
nokiaFac
=
new
NokiaFactory();
Factory
*
motoFac
=
new
MotoFactory();
MobilePhone
*
nokia
=
nokiaFac
->
CreatePhone();
MobilePhone
*
moto
=
motoFac
->
CreatePhone();
nokia
->
call();
nokia
->
shortMsg();
moto
->
call();
moto
->
shortMsg();
BaseStation
*
nokiaBS
=
nokiaFac
->
CreateBaseStation();
BaseStation
*
motoBS
=
motoFac
->
CreateBaseStation();
nokiaBS
->
BSCControl();
nokiaBS
->
BTSControl();
motoBS
->
BSCControl();
motoBS
->
BTSControl();
nokiaFac
->
DestroyBaseStation(nokiaBS);
nokiaFac
->
DestroyPhone(nokia);
motoFac
->
DestroyBaseStation(motoBS);
motoFac
->
DestroyPhone(moto);
return
0
;
}
上面的例子,用图来表示如下图:
7
,总结
(1)
抽象工厂分离了客户和类的实现,客户通过工厂的抽象接口来得到产品的实例,客户不知道产品是如何生成的,具体产品类的名称也不会出现在客户代码中。
(2)
Abstract Factory
中,一个具体的工厂类在一个应用中仅出现一次(在初始化的时候),只需改变具体的工厂即可生产出一系列具有相关性的产品。
(3)
Abstract Factory
和
Factory Method
最大的区别就是:
Factory Method
针对同一级的产品,这些产品往往拥有共同的父类;
Abstract Factory
对应的是多个产品级的结构。所以在涉及到
Abstract Factory
的时候常常提到“产品族”的概念。产品族是指位于不同产品等级结构中,并且功能相互关联的产品系列,比如基站系统和手机属于不同级别的产品,但是他们是联合工作的。
(4)
Abstract Factory
也有不足之处。尤其是扩展新的产品系列,
Abstract Factory
的影响会非常大。比如我们要想新添加
Alcatel
产品系列,
Alcatel
又要生产
MSC
(移动交换中心)这个产品,此时不仅仅
Abstract Factory
需要修改以支持新产品,每个具体工厂类也必须修改(需要添加
MSC
产品的生产接口,尽管可能
Nokia
或者
Moto
不生产
MSC
)。这时,如果在
Abstract Factory
中的为生产
MSC
的接口提供缺省实现,可以避免修改已有具体工厂类(前题:这些具体工厂不负责生产新的产品)。
(5)
通常,
Abstract Factory
在整个应用中只有一个实例,所以可以结合
Singleton
模式。