工厂模式 使用全局变量自己注册

前言

使用工厂模式时,需要将类注册进工厂里,看到一种新的奇技淫巧,使用静态变量来将类注册进工厂。

代码

Product.h

#ifndef PRODUCT_H
#define PRODUCT_H

class Product
{
public:
    Product(){};
    virtual ~Product(){};
    virtual void doWork() = 0;
};
#endif // PRODUCT_H

Factory.h

#ifndef FACTORY_H
#define FACTORY_H

#include <map>
#include <stdexcept>
#include <string>
#include <functional>
#include <memory>
#include "Product.h"

#define REGISTER_FACTORY_VNAME(T) reg_msg_##T##_
#define REGISTER_FACTORY(T, ...) static Factory::register_str<T> REGISTER_FACTORY_VNAME(T)(#T, ##__VA_ARGS__);
#define REGISTER_FACTORY_NAME(T, key, ...) static Factory::register_str<T> REGISTER_FACTORY_VNAME(T)(key, ##__VA_ARGS__);

class Factory
{
public:
    template<typename T>
    struct register_str
    {
        register_str(const std::string& key)
        {
            Factory::get().map_.emplace(key, [] { return new T(); });
        }

        template<typename... Args>
        register_str(const std::string& key, Args... args)
        {
            Factory::get().map_.emplace(key, [&] { return new T(args...); });
        }
    };

    static Product* produce(const std::string& key);

    static std::unique_ptr<Product> produceUnique(const std::string& key);

    static std::shared_ptr<Product> produceShared(const std::string& key);

private:
    Factory();
    Factory(const Factory&) = delete;
    Factory(Factory&&) = delete;

    static Factory& get()
    {
        static Factory instance;
        return instance;
    }

    static std::map<std::string, std::function<Product*()>> map_;
};
#endif // FACTORY_H

Factory.cpp

#include "Factory.h"

std::map<std::string, std::function<Product*()>> Factory::map_;

Product *Factory::produce(const std::string &key)
{
    if (map_.find(key) != map_.end())
        return map_[key]();
    else
        return nullptr;
}

std::unique_ptr<Product> Factory::produceUnique(const std::string &key)
{
    return std::unique_ptr<Product>(produce(key));
}

std::shared_ptr<Product> Factory::produceShared(const std::string &key)
{
    return std::shared_ptr<Product>(produce(key));
}

Factory::Factory() {}
以上就是产品基类 和 工厂代码。

特例化产品

MyProduct.h

#ifndef MYPRODUCT_H
#define MYPRODUCT_H

#include "Product.h"

class MyProduct1 : public Product
{
public:
    MyProduct1();
    virtual ~MyProduct1(){};
    virtual void doWork();
};

class MyProduct2 : public Product
{
public:
    MyProduct2();
    virtual ~MyProduct2(){};
    virtual void doWork();
};
#endif // MYPRODUCT_H

MyProduct.cpp

#include "MyProduct.h"
#include <QDebug>
#include "Factory.h"

REGISTER_FACTORY(MyProduct1);
REGISTER_FACTORY_NAME(MyProduct2, "MyProduct2");
MyProduct1::MyProduct1() {}

void MyProduct1::doWork()
{
    qDebug()<<"MyProduct1::doWork";
}

MyProduct2::MyProduct2()
{

}

void MyProduct2::doWork()
{
    qDebug()<<"MyProduct1::doWork";
}

我们看看 REGISTER_FACTORY_NAME(MyProduct2, “MyProduct2”); 这个宏做了什么。
将宏展开后是

static Factory::register_str<MyProduct2> reg_msg_MyProduct2_("MyProduct2");

是声明了全局静态变量 reg_msg_MyProduct2_,类型是 Factory::register_str。这样 reg_msg_MyProduct2_ 初始化时就会调用 register_str 的构造函数

register_str(const std::string& key)
        {
            Factory::get().map_.emplace(key, [] { return new T(); });
        }

将 new 函数放进 Factory 的 map_ 中,这样就能使用 特定字符串来从工厂里 new一个新对象出来。

使用方式

#include "Factory.h"
#include "MyProduct.h"

int main(int argc, char *argv[])
{
    Product* p = Factory::produce("MyProduct1");
    p->doWork();
    auto p2 = Factory::produceUnique("MyProduct2");
    p2->doWork();
    auto errorPtr = Factory::produceUnique("MyProduct");
    if(errorPtr != nullptr)
    {
        errorPtr->doWork();
    }
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值