C++设计模式——工厂模式(Factory Pattern)

C++设计模式——工厂模式(Factory Pattern)

微信公众号:幼儿园的学霸

目录


工厂模式包括三种:简单工厂模式、工厂方法模式、抽象工厂模式。

工厂模式的主要作用是封装对象的创建,分离对象的创建和操作过程,用于批量管理对象的创建过程,便于程序的维护和扩展。

务必记住这个词:封装. 在工厂模式中,有什么想不通都可以思考一下这个词

简单工厂模式

简单工厂是工厂模式最简单的一种实现,对于不同产品的创建定义一个工厂类,将产品的类型作为参数传入到工厂的创建函数,根据类型分支选择不同的产品构造函数。
其UML类图如下:
简单工厂模式

主要特点:产品创建过程在工厂类中完成,当增加新产品时,需要修改工厂类。使用简单工厂模式,我们只需要知道具体的产品型号就可以创建一个产品。
缺点:工厂类集中了所有产品类的创建逻辑,如果产品量较大,会使得工厂类变的非常臃肿。

(以手机的生产讲解该模式)


#include <bits/stdc++.h>

using std::cout;
using std::endl;

//
//简单工厂模式
//


typedef enum PhoneTypeTag {
    MI_PHONE,
    IPHONE_PHONE,
    HUAWEI_PHONE
} PhoneType;


//产品抽象基类 AbstractProduct
class Phone {
    //添加虚析构函数!
public:
    virtual void type() = 0;//代表共有属性
};

//
//具体的产品类
//

class MiPhone : public Phone {
public:
    void type() override {
        cout << "I'm XiaoMi Phone !" << endl;
    }
};

class IPhone : public Phone {
public:
    void type() override {
        cout << "I'm IPhone !" << endl;
    }
};

class HuaweiPhone : public Phone {
public:
    void type() override {
        cout << "I'm Huawei Phone !" << endl;
    }
};

//工厂类 手机代工厂
class PhoneFactory {
public:
    //根据产品信息创建具体的产品类示例,返回一个抽象产品类
    std::shared_ptr<Phone> MakePhone(const PhoneType type) {
        switch (type) {
            case PhoneType::MI_PHONE:
                return std::make_shared<MiPhone>();
            case PhoneType::IPHONE_PHONE:
                return std::make_shared<IPhone>();
            case PhoneType::HUAWEI_PHONE:
                return std::make_shared<HuaweiPhone>();
            default:
                return nullptr;
        }
    }

};

int main() {
    PhoneFactory phoneFactory;
    std::shared_ptr<Phone> m_phone = nullptr;

    m_phone = phoneFactory.MakePhone(PhoneType::MI_PHONE);
    m_phone->type();

    m_phone = phoneFactory.MakePhone(PhoneType::IPHONE_PHONE);
    m_phone->type();

    m_phone = phoneFactory.MakePhone(PhoneType::HUAWEI_PHONE);
    m_phone->type();

    //动态绑定
    //m_phone = std::make_shared<MiPhone>();
    //m_phone->type();

    return 0;
}

代码运行输出结果如下:

I'm XiaoMi Phone !
I'm IPhone !
I'm Huawei Phone !

看完上面的代码是否有一种疑惑:采用动态绑定,直接new一下不就实现同样的效果了吗。
直接new确实很方便,但是在大型软件开发中这样很危险,用专业术语来说是违反了 依赖倒置原则

高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象

通俗来讲,引入的依赖并不可靠,它一般是第三方库或是其他开发人员实现的代码,在不确定的某一天,里面的代码会被修改甚至是删除。这时候你的代码变的很脆,不知不觉中就崩了。但现实中又不可能不引入其他依赖,所以大家就约定最小依赖引入:依赖提供者将隐藏对象的属性和实现细节,仅对外公开接口(抽象),这就是OOP三大特性之一:封装(另外2个是继承和多态)。因此,也可以说,工厂模式是为了实现封装特性

回看一下上面的代码,我们只调用了工厂类的一个接口CreateProduct就实现了派生方法的动态绑定,这样具体"手机产品"(MiPhone,IPhone,HuaWeiPhone)的修改(如修改了类名)就不影响现有代码了。假设某天"手机工厂"(PhoneFactory)开发者觉得MiPhone子类有了性能更好的实现,他只需在简单工厂里面换一个新的派生类(如SuperMiPhone)即可,而具体的调用者的代码不需要做任何改动。

  1. 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
  2. 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。

工厂模式的最大优点就是屏蔽产品的具体实现,调用者只关心产品的接口。当然,它也有自己的问题,产品种类可能有成千上万,如果都是依靠同一个工厂生产,那么必然会使得工厂代码及其庞大。这就有了工厂方法的设计实现。

工厂方法模式

其实这才是正宗的工厂模式,简单工厂模式只是一个简单的对创建过程封装。

和简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂。

在代码实现上,工厂方法模式在简单工厂模式的基础上增加对工厂的基类抽象,不同的产品创建采用不同的工厂创建(从工厂的抽象基类派生),这样创建不同的产品过程就由不同的工厂分工解决:FactoryA专心负责生产ProductA,FactoryB专心负责生产ProductB,FactoryA和FactoryB之间没有关系;如果到了后期,如果需要生产ProductC时,我们则可以创建一个FactoryC工厂类,该类专心负责生产ProductC类产品。

该模式相对于简单工厂模式的优势在于:便于后期产品种类的扩展。如果需要增加新的产品类,只需要扩展一个相应的工厂类即可。
缺点:产品类数据较多时,需要实现大量的工厂类,这无疑增加了代码量。

#include <bits/stdc++.h>

using std::cout;
using std::endl;

//
//工厂方法模式
//

//产品抽象基类 AbstractProduct
class Phone {
    //添加虚析构函数!
public:
    virtual void type() = 0;//代表共有属性
};

//
//具体的产品类
//

class MiPhone : public Phone {
public:
    void type() override {
        cout << "I'm XiaoMi Phone !" << endl;
    }
};

class IPhone : public Phone {
public:
    void type() override {
        cout << "I'm IPhone !" << endl;
    }
};

class HuaweiPhone : public Phone {
public:
    void type() override {
        cout << "I'm Huawei Phone !" << endl;
    }
};

//抽象工厂类,提供一个创建接口
class PhoneFactory {
public:
    //提供创建产品实例的接口,返回抽象产品类
    virtual std::shared_ptr<Phone> MakePhone() = 0;
};

//具体的创建工厂类,使用抽象工厂类提供的接口,各具体的工厂去创建具体的产品实例
class MiPhoneFactory : public PhoneFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<MiPhone>();
    }
};

class IPhoneFactory : public PhoneFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<IPhone>();
    }
};

class HuaWeiPhoneFactory : public PhoneFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<HuaweiPhone>();
    }
};


int main() {
    std::shared_ptr<Phone> m_pPhone = nullptr;

    m_pPhone = MiPhoneFactory().MakePhone();
    m_pPhone->type();

    m_pPhone = IPhoneFactory().MakePhone();
    m_pPhone->type();

    m_pPhone = HuaWeiPhoneFactory().MakePhone();
    m_pPhone->type();

    return 0;
}

工厂方法减轻了工厂类的负担,新增一种“手机”只需添加一个特定的“手机工厂”即可,这就符合了开放闭合原则

对扩展是开放的;对修改是关闭的

这里提一下,开放闭合原则并不是说接口一成不变,它要求的是增量变化——只增加新方法,不改动旧方法。

抽象工厂模式

工厂方法自然比简单工厂更加灵活,但当业务有所变更时,比如需要添加“手机”的周边产品——“电脑”呢?这时候我们就需要一个更复杂的模式——抽象工厂

抽象工厂是一个产品簇的概念,一个工厂可以生产多种业务相关的产品。我们在工厂方法的基础上扩充一下代码:定义一个抽象工厂接口AbstractFactory,通过不同的方法生产出一个“抽象”产品簇(Phone和PC)。回过头来再看工厂方法,事实上它就是抽象工厂最简单的一种场景设计——只生成一种产品。

抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。

#include <bits/stdc++.h>

using std::cout;
using std::endl;

//
//抽象工厂模式
//

//手机产品抽象基类 AbstractProduct
class Phone {
    //添加虚析构函数!
public:
    virtual void type() = 0;//代表共有属性
};

//
//具体的手机产品类
//

class MiPhone : public Phone {
public:
    void type() override {
        cout << "I'm XiaoMi Phone !" << endl;
    }
};

class IPhone : public Phone {
public:
    void type() override {
        cout << "I'm IPhone !" << endl;
    }
};

class HuaweiPhone : public Phone {
public:
    void type() override {
        cout << "I'm Huawei Phone !" << endl;
    }
};


//PC产品抽象基类 AbstractProduct
class PC {
    //添加虚析构函数!
public:
    virtual void type() = 0;//代表共有属性
};

//
//具体的手机产品类
//

class MiPC : public PC {
public:
    void type() override {
        cout << "I'm XiaoMi PC !" << endl;
    }
};

class MACPC : public PC {
public:
    void type() override {
        cout << "I'm MAC PC !" << endl;
    }
};

class HuaweiPC : public PC {
public:
    void type() override {
        cout << "I'm Huawei PC !" << endl;
    }
};



//抽象工厂类,提供一个创建接口,其中增加PC产品接口
class AbstractFactory {
public:
    //提供创建产品实例的接口,返回抽象产品类
    virtual std::shared_ptr<Phone> MakePhone() = 0;
    virtual std::shared_ptr<PC> MakePC() = 0;
};



//具体的创建工厂类,使用抽象工厂类提供的接口,各具体的工厂去创建具体的产品实例
class MiFactory : public AbstractFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<MiPhone>();
    }

    std::shared_ptr<PC> MakePC() override{
        return std::make_shared<MiPC>();
    }
};

class IPhoneFactory : public AbstractFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<IPhone>();
    }
    std::shared_ptr<PC> MakePC() override{
        return std::make_shared<MACPC>();
    }
};

class HuaWeiFactory : public AbstractFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<HuaweiPhone>();
    }
    std::shared_ptr<PC> MakePC() override{
        return std::make_shared<HuaweiPC>();
    }
};

//另外一个代工厂,生产MiPhone和MAC
class OdmFactory : public AbstractFactory {
public:
    std::shared_ptr<Phone> MakePhone() override {
        return std::make_shared<MiPhone>();
    }
    std::shared_ptr<PC> MakePC() override{
        return std::make_shared<MACPC>();
    }
};



int main()
{
    std::shared_ptr<Phone> m_pPhone = nullptr;
    std::shared_ptr<PC> m_pPC = nullptr;

    MiFactory miFactory;
    IPhoneFactory iPhoneFactory;
    HuaWeiFactory huaWeiFactory;
    OdmFactory odmFactory;

    m_pPhone = miFactory.MakePhone();
    m_pPC = miFactory.MakePC();
    m_pPhone->type();
    m_pPC->type();

    m_pPhone = iPhoneFactory.MakePhone();
    m_pPC = iPhoneFactory.MakePC();
    m_pPhone->type();
    m_pPC->type();

    m_pPhone = huaWeiFactory.MakePhone();
    m_pPC = huaWeiFactory.MakePC();
    m_pPhone->type();
    m_pPC->type();

    m_pPhone = odmFactory.MakePhone();
    m_pPC = odmFactory.MakePC();
    m_pPhone->type();
    m_pPC->type();


    return 0;
}

代码输出如下:

I'm XiaoMi Phone !
I'm XiaoMi PC !
I'm IPhone !
I'm MAC PC !
I'm Huawei Phone !
I'm Huawei PC !
I'm XiaoMi Phone !
I'm MAC PC !

在抽象工厂模式中,增加新的产品族很方便(如可以将IPhone和HuaWeiPC作为一个产品系列,只用增加一个工厂即可),但是增加新的产品等级结构很麻烦(如,增加键盘作为新的产品,那么不仅需要增加新的产品类,同时各个工厂也需要进行对应的调整,将键盘这一产品增加进去)。

总结

工厂模式最直观的理解是,减少new创建对象的方式,用接口的方式来返回一个对象,而new创建的方式被封装了

简单工厂:调用者只需使用单例工厂就可获取同一范畴的所有产品

工厂方法:调用者并不知道它在运行时会获取何种产品,只知道某个特定的工厂能生成出满足需求的产品

抽象工厂:调用者可以在运行时从特定的工厂中获得所有信息相关的产品簇(可以对产品进行组合)

工厂方法模式和抽象工厂模式区别:区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。再通俗深化理解下:工厂模式针对的是一个产品等级结构,抽象工厂模式针对的是面向多个产品等级结构的。

是否可以这样理解呢:工厂方法模式生产一种产品,抽象工厂模式生产一系列产品,构成的是一个生态

参考资料

1.几种常见的设计模式(含C++代码)
2.C++ 常用设计模式(学习笔记)
3.设计模式之工厂模式(factory pattern)



下面的是我的公众号二维码图片,欢迎关注。
图注:幼儿园的学霸

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Abstract Factory Pattern是一种设计模式,它是创建对象的工厂模式的变体,允许对象在运行时被替换。 Abstract Factory模式提供了一种方法,可以创建一组相关或相互依赖的对象,而不需要明确指定其具体类。 下面是一个C语言的代码示例,该代码实现了一个抽象工厂模式,该模式创建一组车辆: ```c #include <stdio.h> typedef struct IVehicle IVehicle; struct IVehicle { void (*Drive)(IVehicle *); }; typedef struct Car Car; struct Car { IVehicle base; int wheelCount; }; void Car_Drive(IVehicle *vehicle) { Car *car = (Car *)vehicle; printf("Driving a car with %d wheels\n", car->wheelCount); } typedef struct Bike Bike; struct Bike { IVehicle base; int pedalCount; }; void Bike_Drive(IVehicle *vehicle) { Bike *bike = (Bike *)vehicle; printf("Riding a bike with %d pedals\n", bike->pedalCount); } typedef struct IVehicleFactory IVehicleFactory; struct IVehicleFactory { IVehicle *(*CreateVehicle)(IVehicleFactory *); }; typedef struct CarFactory CarFactory; struct CarFactory { IVehicleFactory base; }; IVehicle *CarFactory_CreateVehicle(IVehicleFactory *factory) { Car *car = (Car *)malloc(sizeof(Car)); car->base.Drive = &Car_Drive; car->wheelCount = 4; return (IVehicle *)car; } typedef struct BikeFactory BikeFactory; struct BikeFactory { IVehicleFactory base; }; IVehicle *BikeFactory_CreateVehicle(IVehicleFactory *factory) { Bike *bike = (Bike *)malloc(sizeof(Bike)); bike->base.Drive = &Bike_Drive; bike->pedalCount = 2; return (IVehicle *)bike; } int main(int argc, char *argv[]) { CarFactory carFactory = { { &CarFactory_CreateVehicle } }; IVehicle *vehicle = carFactory.base.CreateVehicle((IVehicleFactory *)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值