设计模式系列(六)抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,即产品族,而不需要明确指定具体类。这里利用了依赖倒置原则,即依赖抽象,不要依赖具体。注意到,抽象工厂模式创建的是一个产品族,而不单单是一个产品,这一点是与工厂方法模式不同的。
抽象工厂模式一般需要四个角色,这四个角色与工厂方法模式的基本相同:
(1)抽象工厂角色:这里可以说是一个标准的接口,定义了所有产品的创建方法,形成一个产品族,等待被实现。在java中它由抽象类或者接口来实现,在C++中由抽象类实现。
(2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象,这里具体类的实现也是一个产品族,每个产品使用的是类似于工厂方法模式的形式来创建。
(3)抽象产品角色:这里一般是接口,定义了一种产品的接口,每个产品有自己不同的接口。在java中一般有抽象类或者接口来实现,在C++中由抽象类实现。
(4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例,每个产品可以有很多具体类,注意这里的一族产品和一种产品的不同具体类是不一样的。
(2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象,这里具体类的实现也是一个产品族,每个产品使用的是类似于工厂方法模式的形式来创建。
(3)抽象产品角色:这里一般是接口,定义了一种产品的接口,每个产品有自己不同的接口。在java中一般有抽象类或者接口来实现,在C++中由抽象类实现。
(4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例,每个产品可以有很多具体类,注意这里的一族产品和一种产品的不同具体类是不一样的。
可以看出,这些角色与工厂方法基本一样,那么它们之间的区别在哪里?
(1)抽象工厂模式创建的是一族产品,而工厂方法创建的是一个产品,抽象工厂模式里面其实使用了工厂方法模式,对于每一个产品的创建,其实和工厂方法模式十分类似;
(2)抽象工厂模式采用的是对象组合,将各种产品组合在一个工厂里面,然后由具体类实现,对象的创建被实现在工厂接口所暴露出来的方法中,而工厂方法模式则使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象;
(3)当需要创建产品家族和想制造相关产品的集合时,可以使用抽象工厂模式,而工厂方法可以把客户代码实例化的具体类中解耦,其使用方式很简单,只需要继承成子类,并实现工厂方法即可;
(4)抽象工厂模式更为复杂,工厂方法模式相对于比较简单。
使用抽象工厂模式还要满足下述条件:
(1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
(1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
(2)同属于同一个产品族的产品以其使用。
这里需要特别说明一下产品族,它是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图。当有多个不同的等级结构的产品时,如果使用工厂方法模式就势必要使用多个独立的工厂等级结构来对付这些产品的等级结构。如果这些产品等级结构是平行的,会导致多个平行的工厂等级结构。抽象工厂模式使用同一个 工厂等级结构负责这些不同产品等级结构产品对象的创建。对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。由于每个具体工厂角色都需要负责两个不同等级结构的产品对象的创建,因此每个工厂角色都需要提供两个工厂方法,分别用于创建两个等级结构的产品。既然每个具体工厂角色都需要实现这两个工厂方法,所以具有一般性,不妨抽象出来,移动到抽象工厂角色中加以声明。
抽象工厂模式的优点:它分离了具体的类;它使得易于交换产品系列;它有利于产品的一致性。
抽象工厂模式的缺点:难以支持新种类的产品。
在以下情况下应当考虑使用抽象工厂模式:
(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
(2)这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3)同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
(2)这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3)同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
下面我们来看一个十分详细的例子,这个例子包括的文件依次是:AbstractFactoryPattern.h、AbstractFactoryPattern.cpp、AbstractFactoryPatternTest.cpp。
// 抽象工厂模式
#ifndef ABSTRACTFACTORY
#define ABSTRACTFACTORY
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
using std::string;
using std::vector;
using std::cout;
using std::endl;
// 需要在抽象工厂内创建的产品的抽象产品:调味料和添加品
class Dough // 面团
{
public:
Dough(){}
virtual ~Dough()