C++设计模式之抽象工厂模式
一、缘由
在《C++设计模式之工厂方法模式》一文中我们提到,由于简单工厂模式当中的工厂类职责过重,严重违反了单一职责的原则,导致系统扩展十分困难,于是引出了工厂方法模式,工厂方法模式引入抽象的工厂类,具体的创建工作推迟到每个具体的工厂类中,这样每个具体工厂类只负责一种产品的创建,这样每个具体工厂类的职责就足够单一,足够简单了。而工厂方法模式的缺点也来源于此:类的职责太单一了,导致要完成系统所需的创建工作,在产品类型增加的时候,工厂类也会急剧增加,导致系统中的类过多。那怎么办呢?解决方法很简单:让具体工厂类负责更多的工作,也就是负责不止一种类型的具体产品创建。而是负责一个系列的产品创建。
可是这里问题又来了:这样的模式和简单工厂又有什么区别呢?岂不是又违反了单一职责的原则吗?
答:
1. 简单工厂模式是利用一个工厂类进行系统中所有的产品类行进行创建,而抽象工厂模式则是利用一个工厂类进行一个系列的产品创建。假设有产品手机为诺基亚N系列:N97,N70,N80。诺基亚S系列:6260s,6500s,6700s和诺基亚E50,E61,E71手机。简单工厂利用一个工厂创建了:N97,N70,N80,6260s,6500s,6700s,E50,E61,E71。而抽象工厂模式分别用三个具体工厂类:NFactory、SFactory、EFactory,分别创建了N系列,S系列,E系列的手机。
2. 正如我在《单一职责和里氏替换》一文中说的:如何划分职责只能在具体场景中进行具体划分,不同的需求下,划分可能是不同的。 在简单工厂模式、工厂方法模式,抽象工厂模式中,对于职责的划分分别为:以创建产品为职责,以创建一种产品为职责,一创建一个系列的产品为职责,三种工厂模式的职责划分粒度不同。说到底在何种场合下使用哪种工厂模式,主要看职责划分是否合理。划分职责时,粒度不能太大,也不能太小。粒度太大导致单个类职责过重,难以维护,粒度太小导致类的数量太多,系统变复杂。
二、实现
在抽象工厂模式中,我们然具体工厂类负责更多的职责,在每一个具体工厂类负责同一个产品等级下的所有产品族产品的创建。例如LINUX和WINDOWS处于同一个产品等级,而LINUX PC版本和LINUX移动版本是LINUX这个产品等级下的产品族。这样抽象工厂模式的UML类图如下所示:
三、代码分析
示例代码如下:
#include <iostream>
#include <string>
//产品等级结构A
class ProductA {
public:
virtual void whichType() = 0;
virtual ~ProductA(){}
};
//产品等级结构B
class ProductB {
public:
virtual void whichType() = 0;
virtual ~ProductB(){}
};
//产品族1
class ProductA1 : public ProductA {
public:
virtual void whichType(){std::cout << "ProductA1" << std::endl;}
};
//产品族2
class ProductA2 : public ProductA {
public:
virtual void whichType(){std::cout << "ProductA2" << std::endl;}
};
//产品族1
class ProductB1 : public ProductB {
public:
virtual void whichType(){std::cout << "ProductB1" << std::endl;}
};
//产品族2
class ProductB2 : public ProductB {
public:
virtual void whichType(){std::cout << "ProductB2" << std::endl;}
};
class Factory {
public:
virtual ProductA *createProductA() = 0;
virtual ProductB *createProductB() = 0;
~Factory(){}
};
class Factory1: public Factory{
public:
virtual ProductA *createProductA(){return new ProductA1;}
virtual ProductB *createProductB(){return new ProductB1;}
};
class Factory2: public Factory{
public:
virtual ProductA *createProductA(){return new ProductA2;}
virtual ProductB *createProductB(){return new ProductB2;}
};
int main(void) {
Factory *factory1 = new Factory1;
ProductA *typeA1 = factory1->createProductA();
ProductB *typeB1 = factory1->createProductB();
Factory *factory2 = new Factory2;
ProductA *typeA2 = factory2->createProductA();
ProductB *typeB2 = factory2->createProductB();
typeA1->whichType();
typeB1->whichType();
typeA2->whichType();
typeB2->whichType();
return 0;
}
运行结果:
ProductA1
ProductB1
ProductA2
ProductB2
四、总结
优点:
- 单个具体工厂类负责的职责适量,有利于减少系统中具体工厂类的数量。
- 增加新的产品族很方便,不需要修改已有系统,符合开闭与阿这
缺点:
- 增加新的产品等级结构十分麻烦,需要修改大量的类,甚至需要修改抽象类,违背了开闭原则。
使用场景: 由上面的阐述知道,当产品等级结构稳定的时候,可以使用抽象工厂方法模式。