设计模式C++抽象工厂

设计模式C++抽象工厂

注:参考视频:【设计模式(完整版)】https://www.bilibili.com/video/BV1Zd4y1t7HK?p=3&vd_source=eee55dc084ebc7a8d4f5db673a3c06f9

分类:(对象)创建型

抽象工厂和工厂方法都是创建型,都是为了解决new一个东西,new的行为都不希望过早的绑定.我们希望他延时,延时有两种方法,一种是通过继承,一种是通过多态.

工厂方法就是通过继承,通过继承以后我们可以重写里面的方法(上一篇博客中的Logistics),而抽象工厂则是把业务单独拎出来,把创建和业务分成两个类.

通过对象还是类来解决问题是站在业务层使用者的角度来说.就像在上图client中有一个factory对象,用对象的方式来解决问题.factory的类型就是AbstractFactory接口,它依赖AbstractFactory接口.

问题:家具城里有沙发,椅子,茶几等产品.产品有不同风格,如现代,北欧风,工业.希望客户收到的出产品风格统一,并可以方便的添加新产品和新风格.(这里不同风格相当于苹果手机搭配安卓充电线,我们想要苹果手机搭配苹果充电线这种统一风格的来使用)

如上图,AbstractFactory就像是一个代工厂,生产两种品牌不同的手机,ConcreteFactory1生产安卓手机,ConcreteProductA1就是生产安卓手机,ConcreteProductB1就是生产安卓手机充电线.ConcreteFactory2生产苹果手机,ConcreteProductA2就是生产苹果手机,ConcreteProductB2就是生产苹果手机充电线.他们生产的ProductA和ProductB都是手机和充电线,通过ConcreteFactory1生产的都是安卓手机配套设备,通过ConcreteFactory2生产的都是苹果手机配套设备,不会乱.

在这个层次上说:工厂方法是一个抽象工厂的一个特例.

例如:我们把AbstractFactory和Client合在一起,换个名字叫Creator,把someOperation()设置为纯虚函数,写两个派生类继承Creator,然后重写someOperation()方法,把new延迟到派生类中创建,左边产品简化一下,灭有ConcreteA1,ConcreteB1,只有ProductA(卡车运输),ProductB(轮船运输),那这样就是工厂方法了.

返回问题:不使用设计模式的原始代码:

#include <iostream>
class Chair
{
public:
    virtual ~Chair() {}
    virtual void SitOn() const = 0;
};
class ModernChair :public Chair
{
public:
    virtual ~ModernChair() {}
    virtual void SitOn() const override
    {
        std::cout << "可以被坐下的ModernChair" << std::endl;
    }
};
class ChineseChair :public Chair
{
public:
    virtual ~ChineseChair() {}
    virtual void SitOn() const override
    {
        std::cout << "可以被坐下的ChineseChair" << std::endl;
    }
}; 
​
class Table
{
public:
    virtual ~Table() {}
    virtual void LayOn() const = 0;
};
class ModernTable :public Table
{
public:
    virtual ~ModernTable() {}
    virtual void LayOn() const override
    {
        std::cout << "可以放东西的ModernTable" << std::endl;
    }
};
class ChineseTable :public Table
{
public:
    virtual ~ChineseTable() {}
    virtual void LayOn() const override
    {
        std::cout << "可以放东西的ChineseTable" << std::endl;
    }
};
​
class Client
{
public:
    void buyFurniture()
    {
        Chair* chair = new ChineseChair();
        Table* table = new ModernTable();
        chair->SitOn();
        table->LayOn();
​
        delete chair;
        delete table;
    }
};
int main()
{
    Client client;
    client.buyFurniture();
}
​

由上代码可知,我们new chair和new table时没有办法保证风格的统一,而且客户每次买东西都要重新修改Client类.

解决方案:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们确定的类.

我们首先保证风格统一,让他new出来的椅子凳子都是ModernStyle,此时使用多态,我们根据抽象工厂的类图,按照延后new的想法来创建类.

#include <iostream>
class Chair
{
public:
    virtual ~Chair() {}
    virtual void SitOn() const = 0;
};
class ModernChair :public Chair
{
public:
    virtual ~ModernChair() {}
    virtual void SitOn() const override
    {
        std::cout << "可以被坐下的ModernChair" << std::endl;
    }
};
class ChineseChair :public Chair
{
public:
    virtual ~ChineseChair() {}
    virtual void SitOn() const override
    {
        std::cout << "可以被坐下的ChineseChair" << std::endl;
    }
}; 
​
class Table
{
public:
    virtual ~Table() {}
    virtual void LayOn() const = 0;
};
class ModernTable :public Table
{
public:
    virtual ~ModernTable() {}
    virtual void LayOn() const override
    {
        std::cout << "可以放东西的ModernTable" << std::endl;
    }
};
class ChineseTable :public Table
{
public:
    virtual ~ChineseTable() {}
    virtual void LayOn() const override
    {
        std::cout << "可以放东西的ChineseTable" << std::endl;
    }
};
//新加类
class FurnitureFactory // 抽象工厂
{
public:
    virtual Chair* createChair() const = 0;
    virtual Table* createTable() const = 0;
};
//新加类 一个具体的生产ModernStyle的工厂 
class ModernStyleFactory :public FurnitureFactory 
{
public:
    virtual Chair* createChair() const override
    {
        return new ModernChair();
    }
    virtual Table* createTable() const override
    {
        return new ModernTable();
    }
};
class Client
{
//新加代码 添加一个构造函数,里面传递modern或chinese风格的家具
private:
    FurnitureFactory* m_factory;
public:
    Client(FurnitureFactory* factory)
    {
        setFactroy(factory);
    }
    void buyFurniture()
    {
        //Chair* chair = new ChineseChair();
        //Table* table = new ModernTable();
        Chair* chair = m_factory->createChair();
        Table* table = m_factory->createTable();
        chair->SitOn();
        table->LayOn();
​
        delete chair;
        delete table;
    }
    void setFactory(FurnitureFactory* factory)
    {
        m_factory = factory;
    }
};
int main()
{
    ModernStyleFactory modernFactory;
    Client client(&modernFactory);
    client.buyFurniture();
}

而我们添加一个chinese风格的家具也是很简单(放到文章底部了),再来回顾一下抽象工厂类图

client中有一个对象factory,factory依赖于AbstractFactory这个接口,真正的业务在client里面,我们可以通过构造函数来设置factory,也可以通过函数成员setFactory来设置factory,当我们要创建一个具体的产品时,我们要考虑兼容性(苹果手机只能搭配苹果充电线),所以是一族一族的生产(苹果手机和苹果充电线是一个族),所以在例子中命名我们以风格命名而不是以具体的家具(椅子凳子这类)命名.创建根据族来一系列创建.

另一个例子:跨平台UI

跨平台的UI要用到Button和CheckBox,Window平台就用Window的UI,Mac平台的就用Mac的UI,总之要创建就创建一族的UI.而用户去使用的时候就直接利用多态来延迟这种new.这样使用的时候就不会出现我WinButton却搭配了一个MacCheckbox这种问题.

优点:

将一个系列的产品族统一到一起创建.确保系列产品的兼容性

避免客户端和具体产品代码的耦合

单一职责原则.将产品生成代码抽取到同一位置,使得代码易于维护.

开闭原则.向应用程序中引入新产品族时,无需修改客户端代码.

缺点:

在产品族中拓展新的产品需要修改抽象工厂的接口代码.

完整代码:

#include <iostream>
class Chair
{
public:
    virtual ~Chair() {}
    virtual void SitOn() const = 0;
};
class ModernChair :public Chair //ConcreteProductA1
{
public:
    virtual ~ModernChair() {}
    virtual void SitOn() const override
    {
        std::cout << "可以被坐下的ModernChair" << std::endl;
    }
};
class ChineseChair :public Chair //ConcreteProductA2
{
public:
    virtual ~ChineseChair() {}
    virtual void SitOn() const override
    {
        std::cout << "可以被坐下的ChineseChair" << std::endl;
    }
}; 
​
class Table
{
public:
    virtual ~Table() {}
    virtual void LayOn() const = 0;
};
class ModernTable :public Table //ConcreteProductB1
{
public:
    virtual ~ModernTable() {}
    virtual void LayOn() const override
    {
        std::cout << "可以放东西的ModernTable" << std::endl;
    }
};
class ChineseTable :public Table //ConcreteProductB2
{
public:
    virtual ~ChineseTable() {}
    virtual void LayOn() const override
    {
        std::cout << "可以放东西的ChineseTable" << std::endl;
    }
};
//新加类
class FurnitureFactory // 抽象工厂 AbstractFactory
{
public:
    virtual Chair* createChair() const = 0;
    virtual Table* createTable() const = 0;
};
//新加类
class ModernStyleFactory :public FurnitureFactory //ConcreteFactory1
{
public:
    virtual Chair* createChair() const override
    {
        return new ModernChair();
    }
    virtual Table* createTable() const override
    {
        return new ModernTable();
    }
};
//新加类
class ChineseStyleFactory :public FurnitureFactory //ConcreteFactory2
{
public:
    virtual Chair* createChair() const override
    {
        return new ChineseChair();
    }
    virtual Table* createTable() const override
    {
        return new ChineseTable();
    }
};
​
class Client  //Client
{
//新加代码
private:
    FurnitureFactory* m_factory;
public:
    Client(FurnitureFactory* factory)
    {
        setFactory(factory);
    }
    void buyFurniture()
    {
        //Chair* chair = new ChineseChair();
        //Table* table = new ModernTable();
        Chair* chair = m_factory->createChair();
        Table* table = m_factory->createTable();
        chair->SitOn();
        table->LayOn();
​
        delete chair;
        delete table;
    }
    void setFactory(FurnitureFactory* factory)
    {
        m_factory = factory;
    }
};
int main()
{
    ModernStyleFactory modernFactory;
    Client client(&modernFactory);
    client.buyFurniture();
​
    ChineseStyleFactory chineseFactory;
    client.setFactory(&chineseFactory);
    client.buyFurniture();
}

  • 26
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值