常用项目中,工厂模式通常会采用swith的方式进行创建,随着类型的不断增加,就会疯狂增加switch的case项,为了解决这个问题,采用动态注册的方式实现工厂实例的创建。实现思路上,通过提前注册key和构造器,然后在需要创建的地方通过key来找到构造器从何构造出目标对象。代码如下:
/********************************************************************************
* Copyright(c) 2023-2030 All rights reserved.
* - Filename
* - Author Vincent
* - Version V1.0.0
* - Date 2024/02/11
* - Brief
* - FunctionList:
******************************************************************************
* History:
*
*
*
******************************************************************************
*/
#pragma once
#include <map>
#include <memory>
#include <functional>
#include "factory.hpp"
namespace factory
{
class DynamicFactory
{
public:
template <typename T>
struct Register
{
/// @brief 注册不带参的类构造函数
/// @param name 类名称
inline Register(const std::string &name)
{
DynamicFactory::get()._factoryMap.emplace(name, []
{ return new T(); });
}
/// @brief 注册带参的类构造函数
/// @param name 类名称
template <typename... Args>
inline Register(const std::string &name, Args... args)
{
DynamicFactory::get()._factoryMap.emplace(name, [&]
{ return new T(args...); });
}
};
/// @brief 返回具体的类指针,这里采用dynamic_pointer_cast进行基类指针转换到派生指针。
/// @param name 类名称
/// @return
template <typename DeriveClass, typename T = DeriveClass>
inline std::shared_ptr<T> produce_shared_ptr(const std::string &name)
{
if (_factoryMap.find(name) == _factoryMap.end())
throw std::invalid_argument("the service_id is not exist!");
return std::dynamic_pointer_cast<T>(std::shared_ptr<BaseFactory>(_factoryMap[name]()));
}
/// @brief 动态工厂的单例
/// @return 动态
inline static DynamicFactory &get()
{
static DynamicFactory instance;
return instance;
}
private:
DynamicFactory(){};
DynamicFactory(const DynamicFactory &) = delete;
DynamicFactory(DynamicFactory &&) = delete;
std::map<std::string, std::function<BaseFactory *()>> _factoryMap;
};
};
#define REGISTER_FACTORY_WITH_PARAM(T, name, ...) static factory::DynamicFactory::Register<T>(factory_##T##_)(name, ##__VA_ARGS__);
使用方法:
#include "DynamicFactory.hpp"
#include "factory1.hpp"
#include "factory2.hpp"
#include <iostream>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include <chrono>
bool isExit = false;
void signal_hander_fun(int signum)
{
isExit = true;
printf("catch signal %d\n", signum);
}
int main(int argc, char *argv[])
{
signal(SIGINT, signal_hander_fun);
REGISTER_FACTORY_WITH_PARAM(Factory1, "factory1");
REGISTER_FACTORY_WITH_PARAM(Factory2, "factory2");
auto factory1 = factory::DynamicFactory::get().produce_shared_ptr<Factory1>("factory1");
factory1->printf();
auto factory2 = factory::DynamicFactory::get().produce_shared_ptr<Factory2>("factory2");
factory2->printf();
while (!isExit)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
运行: