之前讲到了C++设计模式——工厂方法模式,我们可能会想到,后期产品会越来越多了,建立的工厂也会越来越多,工厂进行了增长,工厂变的凌乱而难于管理;而且由于工厂方法模式创建的对象都是继承于Product的,所以工厂方法模式中,每个工厂只能创建同一产品族的产品,当需要生产一种全新的产品(不继承自Product)时,发现工厂方法是心有余而力不足。
因此抽象工厂模式应运而生
UML类图:
现在要讲的抽象工厂模式,就是工厂方法模式的扩展和延伸,但是抽象工厂模式,更有一般性和代表性;它具有工厂方法具有的优点,也增加了解决实际问题的能力。
抽象工厂模式的通用源码类图:
注意类图上的圈圈、框框相对应,两个抽象的产品类可以有关系,例如共同继承或实现一个抽象类或接口。
#include
using namespace std;// Product A
class ProductA
{
public:virtual void Show() = 0;
};class ProductA1 : public ProductA
{
public:void Show(){cout<<"I'm ProductA1"<
public:void Show(){cout<<"I'm ProductA2"<
public:virtual void Show() = 0;
};class ProductB1 : public ProductB
{
public:void Show(){cout<<"I'm ProductB1"<
public:void Show(){cout<<"I'm ProductB2"<
public:virtual ProductA *CreateProductA() = 0;virtual ProductB *CreateProductB() = 0;
};class Factory1 : public Factory
{
public:ProductA *CreateProductA(){return new ProductA1();}ProductB *CreateProductB(){return new ProductB1();}
};class Factory2 : public Factory
{ProductA *CreateProductA(){return new ProductA2();}ProductB *CreateProductB(){return new ProductB2();}
};int main(int argc, char *argv[])
{Factory *factoryObj1 = new Factory1();ProductA *productObjA1 = factoryObj1->CreateProductA();ProductB *productObjB1 = factoryObj1->CreateProductB();productObjA1->Show();productObjB1->Show();Factory *factoryObj2 = new Factory2();ProductA *productObjA2 = factoryObj2->CreateProductA();ProductB *productObjB2 = factoryObj2->CreateProductB();productObjA2->Show();productObjB2->Show();if (factoryObj1 != NULL){delete factoryObj1;factoryObj1 = NULL;}if (productObjA1 != NULL){delete productObjA1;productObjA1= NULL;}if (productObjB1 != NULL){delete productObjB1;productObjB1 = NULL;}if (factoryObj2 != NULL){delete factoryObj2;factoryObj2 = NULL;}if (productObjA2 != NULL){delete productObjA2;productObjA2 = NULL;}if (productObjB2 != NULL){delete productObjB2;productObjB2 = NULL;}
}
有N个产品族,在抽象工厂类中就应该有N个创建方法,比如有A、B,两个产品族,就要创建两个方法用于创建A、B两个产品族的对象,至于具体创建的是产品族中哪一个产品的对象,则结合业务情况进行分析,比如A产品族有A1、A2 两个产品,B产品族有B1、B2两个产品,抽象工厂类中的两个方法分别是创建A产品族对象和B产品族对象的,创建A产品族对象的方法到底是创建A1还是A2,创建B产品族对象的方法到底是创建B1还是B2,这是要结合实际业务情况进行分析的。
有M条生产线就应该实现M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。就比如创建A1、B1是一条生产线,创建A2、B2是一条生产线,那就需要两个实现工厂类,第一个实现工厂类中创建A1、B1,第二个实现工厂类中创建A2、B2。
下面通过女娲造人来更加深入地理解抽象工厂模式,具体代码如下:
#include
using namespace std;//多个产品族共同基础Human类
class Human
{
public://每个人种都有相应的颜色virtual void getColor() = 0;//人类会说话virtual void talk() = 0;//每个人都有性别virtual void getSex() = 0;
};//这里有3个产品族,分别是黄色人种、白色人种和黑色人种
class YellowHuman : public Human
{
public:void getColor(){cout << "黄种人的颜色是黄色的" << endl;}void talk(){cout << "黄种人说话一般是双字节" << endl;}
};class WhiteHuman :public Human
{
public:void getColor(){cout << "白种人的颜色是白色的" << endl;}void talk(){cout << "白种人说话一般是单字节" << endl;}
};class BlackHuman :public Human
{
public:void getColor(){cout << "黑种人的颜色是黑色的" << endl;}void talk(){cout << "黑种人说话一般人听不懂" << endl;}
};//产品族创建完毕后开始创建具体产品,每个产品族有两个产品
class YellowFemale:public YellowHuman
{
public:void getSex(){cout << "这是一个黄人女性" << endl;}
};class YellowMale :public YellowHuman
{
public:void getSex(){cout << "这是一个黄人男性" << endl;}
};class WhiteFemale :public WhiteHuman
{
public:void getSex(){cout << "这是一个白人女性" << endl;}
};class WhiteMale :public WhiteHuman
{
public:void getSex(){cout << "这是一个白人男性" << endl;}
};class BlackFemale :public BlackHuman
{
public:void getSex(){cout << "这是一个黑人女性" << endl;}
};class BlackMale :public BlackHuman
{
public:void getSex(){cout << "这是一个黑人男性" << endl;}
};//创建一个抽象工厂类
//有3个产品族,因此抽象工厂类需要有3个方法,分别创建不同产品族的某个产品的对象
class HumanFactory
{
public://创建一个黄种人virtual Human* createYellow() = 0;//创建一个白种人virtual Human* createWhite() = 0;//创建一个黑种人virtual Human* createBlack() = 0;
};//有两条生产线,创建女人和男人,因此有两个工厂实现类
//创建女人工厂实现类
class FemaleFactory :public HumanFactory
{
public:Human* createYellow(){//创建黄人女性return new YellowFemale();}Human* createWhite(){//创建白人女性return new WhiteFemale();}Human* createBlack(){//创建黑人女性return new BlackFemale();}
};//创建男人实现工厂类
class MaleFactory :public HumanFactory
{
public:Human* createYellow(){//创建黄人男性return new YellowMale();}Human* createWhite(){//创建白人男性return new WhiteMale();}Human* createBlack(){//创建黑人男性return new BlackMale();}
};int main()
{HumanFactory* maleFactory = new MaleFactory();HumanFactory* femaleFactory = new FemaleFactory();//工厂建立完毕,开始生产人//创建一个黄人男性Human* yellowMale = maleFactory->createYellow();//创建一个黄人女性Human* yellowFemale = femaleFactory->createYellow();yellowMale->getColor();yellowMale->getSex();yellowMale->talk();yellowFemale->talk();yellowFemale->getColor();yellowFemale->getSex();return 0;if(yellowMale != NULL){delete yellowMale;yellowMale = NULL;}if(yellowFemale != NULL){delete yellowFemale;yellowFemale = NULL;}}
抽象工厂模式的优点:
抽象工厂模式的缺点:
抽象工厂模式的最大缺点就是产品族扩展非常困难,为什么这么说呢?我们以最开始的通用代码为例,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,看看我们的程序有多大改动吧!抽象类AbstractCreator要增加一个方法createProductC(),然后两个实现类都要修改,想想看,这严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约。改变契约,所有与契约有关系的代码都要修改,那么这段代码叫什么?叫“有毒代码”,——只要与这段代码有关系,就可能产生侵害的危险!
适用场合:
工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,主要用于创建一组不同产品族却彼此相关的产品,为它们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以派上用场。
参考资料:
下一篇:B端权限设计