searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一个自动注册的工厂类开发实例

2023-09-04 10:36:14
11
0

1. 首先定义一个抽象工厂类:

class SlotServiceAbstract {
public:
    SlotServiceAbstract() {}
    ~SlotServiceAbstract() {}
    virtual void Print(std::string msg) = 0;
};

2. 单例模式实现对象工厂

register_t是工厂内部的模板类,只有一个构造函数,在构造函数中访问工厂的map_,把子类的key和构造函数注册进去。支持无参构造和带参构造两种。

produce函数通过子类的key查找map,执行register_t中注册的lamda,生成对应的子类实例返回。

get函数返回单例的工厂实例。

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

    SlotServiceAbstract* produce(const std::string& key) {
        if(map_.find(key) == map_.end()) {
            throw std::invalid_argument("the service key is not supported!");
        }
        return map_[key]();
    }
    std::shared_ptr<SlotServiceAbstract> produce_shared(const std::string& key)
    {
        return std::shared_ptr<SlotServiceAbstract>(produce(key));
    }
    static SlotServiceFactory& get()
    {
        static SlotServiceFactory instance;
        return instance;
    }

private:
    SlotServiceFactory() {}
    SlotServiceFactory(const SlotServiceFactory&) = delete;
    SlotServiceFactory(SlotServiceFactory&&) = delete;

    std::unordered_map<std::string, std::function<SlotServiceAbstract *()>> map_;

};

3. 在工厂类头文件中,声明两个宏定义,用于自动注册。

#define REGISTER_SLOT_SERVICE_VNAME(T) reg_msg##T##_
#define REGISTER_SLOT_SERVICE(T, key, ...) static SlotServiceFactory::register_t<T> REGISTER_SLOT_SERVICE_VNAME(T)(key, ##__VA_ARGS__)

4. 实现一个子类,并在子类头文件中调用REGISTER宏实现自动注册

class KvSlotService : public SlotServiceAbstract {
     KvSlotService() {}
    ~KvSlotService() {}
    void print(std::string msg) { std::cout << "KvSlotService:" << msg << std::endl;}
}
REGISTER_SLOT_SERVICE(KvSlotService, "KvService");

 

子类头文件被引用的时候,就相当于自动执行了REGISTER语句,把这个子类注册到工厂map中了。

到此,两个头文件就实现了简单的自动注册工厂类。后面使用的地方执行:SlotServiceFactory::get().produce("KvService")就能生成我想要的KvSlotService实例了。

0条评论
0 / 1000
王****威
4文章数
0粉丝数
王****威
4 文章 | 0 粉丝
原创

一个自动注册的工厂类开发实例

2023-09-04 10:36:14
11
0

1. 首先定义一个抽象工厂类:

class SlotServiceAbstract {
public:
    SlotServiceAbstract() {}
    ~SlotServiceAbstract() {}
    virtual void Print(std::string msg) = 0;
};

2. 单例模式实现对象工厂

register_t是工厂内部的模板类,只有一个构造函数,在构造函数中访问工厂的map_,把子类的key和构造函数注册进去。支持无参构造和带参构造两种。

produce函数通过子类的key查找map,执行register_t中注册的lamda,生成对应的子类实例返回。

get函数返回单例的工厂实例。

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

    SlotServiceAbstract* produce(const std::string& key) {
        if(map_.find(key) == map_.end()) {
            throw std::invalid_argument("the service key is not supported!");
        }
        return map_[key]();
    }
    std::shared_ptr<SlotServiceAbstract> produce_shared(const std::string& key)
    {
        return std::shared_ptr<SlotServiceAbstract>(produce(key));
    }
    static SlotServiceFactory& get()
    {
        static SlotServiceFactory instance;
        return instance;
    }

private:
    SlotServiceFactory() {}
    SlotServiceFactory(const SlotServiceFactory&) = delete;
    SlotServiceFactory(SlotServiceFactory&&) = delete;

    std::unordered_map<std::string, std::function<SlotServiceAbstract *()>> map_;

};

3. 在工厂类头文件中,声明两个宏定义,用于自动注册。

#define REGISTER_SLOT_SERVICE_VNAME(T) reg_msg##T##_
#define REGISTER_SLOT_SERVICE(T, key, ...) static SlotServiceFactory::register_t<T> REGISTER_SLOT_SERVICE_VNAME(T)(key, ##__VA_ARGS__)

4. 实现一个子类,并在子类头文件中调用REGISTER宏实现自动注册

class KvSlotService : public SlotServiceAbstract {
     KvSlotService() {}
    ~KvSlotService() {}
    void print(std::string msg) { std::cout << "KvSlotService:" << msg << std::endl;}
}
REGISTER_SLOT_SERVICE(KvSlotService, "KvService");

 

子类头文件被引用的时候,就相当于自动执行了REGISTER语句,把这个子类注册到工厂map中了。

到此,两个头文件就实现了简单的自动注册工厂类。后面使用的地方执行:SlotServiceFactory::get().produce("KvService")就能生成我想要的KvSlotService实例了。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0