C++设计模式之抽象工厂模式

之前讲到了C++设计模式——工厂方法模式,我们可能会想到,后期产品会越来越多了,建立的工厂也会越来越多,工厂进行了增长,工厂变的凌乱而难于管理;而且由于工厂方法模式创建的对象都是继承于Product的,所以工厂方法模式中,每个工厂只能创建同一产品族的产品,当需要生产一种全新的产品(不继承自Product)时,发现工厂方法是心有余而力不足。

因此抽象工厂模式应运而生

UML类图:

现在要讲的抽象工厂模式,就是工厂方法模式的扩展和延伸,但是抽象工厂模式,更有一般性和代表性;它具有工厂方法具有的优点,也增加了解决实际问题的能力。
在这里插入图片描述

抽象工厂模式的通用源码类图:

在这里插入图片描述

注意类图上的圈圈、框框相对应,两个抽象的产品类可以有关系,例如共同继承或实现一个抽象类或接口。

#include <iostream>
using namespace std;

// Product A
class ProductA
{
public:
    virtual void Show() = 0;
};

class ProductA1 : public ProductA
{
public:
    void Show()
    {
        cout<<"I'm ProductA1"<<endl;
    }
};

class ProductA2 : public ProductA
{
public:
    void Show()
    {
        cout<<"I'm ProductA2"<<endl;
    }
};

// Product B
class ProductB
{
public:
    virtual void Show() = 0;
};

class ProductB1 : public ProductB
{
public:
    void Show()
    {
        cout<<"I'm ProductB1"<<endl;
    }
};

class ProductB2 : public ProductB
{
public:
    void Show()
    {
        cout<<"I'm ProductB2"<<endl;
    }
};

// Factory
class Factory
{
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 <iostream>
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;
	}
	
}

抽象工厂模式的优点:

  • 封装性,每个产品的实现类不是高层模块要关心的,它要关心的是什么?是接口,是抽象,它不关心对象是如何创建出来,这由谁负责呢?工厂类,只要知道工厂类是谁,我就能创建出一个需要的对象,省时省力,优秀设计就应该如此。
  • 产品族内的约束为非公开状态。例如生产男女比例的问题上,猜想女娲娘娘肯定有自己的打算,不能让女盛男衰,否则女性的优点不就体现不出来了吗?那在抽象工厂模式,就应该有这样的一个约束:每生产1个女性,就同时生产出1.2个男性,这样的生产过程对调用工厂类的高层模块来说是透明的,它不需要知道这个约束,我就是要一个黄色女性产品就可以了,具体的产品族内的约束是在工厂内实现的。

抽象工厂模式的缺点:

抽象工厂模式的最大缺点就是产品族扩展非常困难,为什么这么说呢?我们以最开始的通用代码为例,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,看看我们的程序有多大改动吧!抽象类AbstractCreator要增加一个方法createProductC(),然后两个实现类都要修改,想想看,这严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约。改变契约,所有与契约有关系的代码都要修改,那么这段代码叫什么?叫“有毒代码”,——只要与这段代码有关系,就可能产生侵害的危险!

适用场合:

工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,主要用于创建一组不同产品族却彼此相关的产品,为它们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以派上用场。

参考资料:

  • 《设计模式之禅》
  • https://www.cnblogs.com/ring1992/p/9592713.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子非鱼Swx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值