c++工厂模式总结

工厂模式种类

工厂模式的实现方式可分别简单工厂模式、工厂方法模式、抽象工厂模式
此文重点讲最优的工厂方法。

单工厂模式

特点

工厂类封装了创建具体产品对象的函数。

缺陷

扩展性非常差,新增产品的时候,需要去修改工厂类。

工厂方法模式

UML
在这里插入图片描述

特点

1.工厂方法模式抽象出了工厂类,提供创建具体产品的接口,交由子类去实现。
2.工厂方法模式的应用并不只是为了封装具体产品对象的创建,而是要把具体产品对象的创建放到具体工厂类实现。

缺陷

1.每新增一个产品,就需要增加一个对应的产品的具体工厂类。相比简单工厂模式而言,工厂方法模式需要更多的类定义。
2.一条生产线只能一个产品。

抽象工厂模式

UML
在这里插入图片描述

特点

提供一个接口,可以创建多个产品族中的产品对象。如创建耐克工厂,则可以创建耐克鞋子产品、衣服产品、裤子产品等。

缺陷

同工厂方法模式一样,新增产品时,都需要增加一个对应的产品的具体工厂类。

三个工厂总结

1.简单工厂模式,,需要去修改工厂类,这违背了开闭法则。
2.工厂方式模式和抽象工厂模式,都需要增加一个对应的产品的具体工厂类,这就会增大了代码的编写量。

学到的工厂方式模式nb封装方法

IFactor.h

#ifndef IFACTOR_H
#define IFACTOR_H

#include <map>
#include <string>

// 抽象产品工具类
template<class AbstractProduct>
class AbstractProductTool
{
public:
    virtual AbstractProduct* creatProduct() = 0;
protected:
    AbstractProductTool(){}
    ~AbstractProductTool(){}
};

// 工厂模板类。所有 AbstractProduct 的继承者们对象都用此来创建; AbstractProduct 抽象产品类型的接口如“战斗机”
template<class AbstractProduct>
class ProductFactory
{
public:
    static ProductFactory<AbstractProduct> &instance() {
        static ProductFactory<AbstractProduct> factory;
        return factory;
    }

    void registerProduct(const std::string &name, AbstractProductTool<AbstractProduct>* adsProductTool) {
        m_registerProductMap[name] = adsProductTool;
    }

    AbstractProduct* createProduct(const std::string &name) {
        if (m_registerProductMap.find(name) != m_registerProductMap.end())
            return m_registerProductMap[name]->creatProduct();
        else
            return nullptr;
    }

private:
    ProductFactory(){}
    ProductFactory(const ProductFactory&){}
    ProductFactory& operator=(const ProductFactory&){}

    std::map<std::string, AbstractProductTool<AbstractProduct>* > m_registerProductMap;
};

// 具体产品工具类,实例化时会将工厂对象注册进 单例的factory; AbstractProduct 相当于工厂的类型如“战斗机”, ConcreteProduct 继承接口的具体产品类如“F22”
template<class AbstractProduct, class ConcreteProduct>
class ConcreteProductTool :public AbstractProductTool<AbstractProduct>
{
public:
    explicit ConcreteProductTool(const std::string& name) {
        ProductFactory<AbstractProduct>::instance().registerProduct(name, this);
    }

    AbstractProduct* creatProduct() override {
        return new ConcreteProduct();
    }
};

// 利用全局静态变量的初始化特性实现产品类的自注册
#define RegisterProduct(AbstractProduct, ConcreteProduct) \
    static ConcreteProductTool<AbstractProduct, ConcreteProduct> register##ConcreteProduct(#ConcreteProduct);



#endif // IFACTOR_H

IFighter.h

#ifndef IFIGHTER_H
#define IFIGHTER_H

class Fighter
{
protected:
    Fighter(){}
    virtual ~Fighter(){}
public:
    virtual void fly() = 0;
};

#endif // IFIGHTER_H

ITank.h

#ifndef ITANK_H
#define ITANK_H

class Tank
{
protected:
    Tank(){}
    virtual ~Tank(){}
public:
    virtual void fire() = 0;
};

#endif // ITANK_H

main.cpp

#include <iostream>
#include "./inc/IFactor.h"
#include "TianQi.h"
#include "GuangLing.h"
#include "F22.h"
#include "Jian20.h"

using namespace std;

#define sticky(x) hello##x//合并操作符##将出现在其左右的字符序列合并成一个新的标识符
#define str(y) #y//将传入的参数变为字符串,字符串化

// 将“F22” 这个战斗机类型注册进工厂
RegisterProduct(Fighter, F22);
RegisterProduct(Fighter, Jian20);
// 将 RegisterProduct 宏展开,其实就是实例化模板类 ConcreteProductTool
static ConcreteProductTool<Tank, TianQi> registerConcreteProduct("TianQi");
RegisterProduct(Tank, GuangLing);

int main()
{
    // 宏定义解释
    int helloWorld = 10;
    cout<< sticky(World) <<endl;     // 将hello和World链接形成helloWorld ,helloWorld 是一个变量
    cout<< str(hello) <<endl;    // 将helloWorld 变为字符串

    // Fighter 工厂单例,然后生产 F22 战机
    Fighter *USAFighter_1 = ProductFactory<Fighter>::instance().createProduct("F22");
    USAFighter_1->fly();
    Fighter *ChinaFighter_1 = ProductFactory<Fighter>::instance().createProduct("Jian20");
    ChinaFighter_1->fly();

    // Tank 工厂单例,然后生产 TianQi 坦克
    Tank *ChinaTank_1 = ProductFactory<Tank>::instance().createProduct("TianQi");
    ChinaTank_1->fire();
    Tank *USATank_1 = ProductFactory<Tank>::instance().createProduct("GuangLing");
    USATank_1->fire();

    return 0;
}

“TianQi.h”\ “GuangLing.h”“F22.h”\ "Jian20.h“ 与其CPP已省略。
程序输出:

10
hello
fast!
faster!
peng peng peng
zhi zhi zhi

总结

如最后的代码所示,我都有 “TianQi.h”\ “GuangLing.h”“F22.h”\ "Jian20.h“ 四个头文件了。我直接new对象不就行了。为何非得用工厂?
其实:上述只是介绍工厂模式,代码不是很贴合。
工厂模式目的:

(1)解耦:把对象的创建和使用的过程分开

(2)降低代码重复:如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。

(3)降低维护成本:由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建某个对象的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。
使用场景:

  1. 对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。

2.类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值