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实例了。