1. 适用场景
c++开发过程中使用工厂模式创建各种类对象的时候可能需要写一堆的’if-else’函数来根据传入的参数类型创建不同的类对象; 尤其是多态的情况下返回基类指针的情况. 例如:
class B -> class A // B继承A
class C -> class A // C继承A
A *Create(type)
{
if (type == B) return new (std::nothrow) B;
if (type == C) return new (std::nothrow) C;
return nullptr;
}
以上场景在开发中很常见, 但是如果继承关系复杂, 这样的代码需要不停修改代码, 不是很合理. 比较好的方式是实现类似:
B *p = static_cast<B *>(Create("B"));
C *p = static_cast<B *>(Create("C"));
这样的效果. 其实就是JAVA中的反射机制的体现, 实际c++本身是不支持的, 但是可以通过曲线救国的方式来实现.
2. 实现思路
核心: 通过回调函数来实现创建.
步骤: 1> 创建一个单例工厂类, 类中维护一个类名和创建对应类的回调函数的映射关系(map) 2> 需要创建的时候根据传入的类名参数查找对应的回调函数来创建类
3. 具体实现代码
main.cpp
#include "class_factory.h"
class CReflex
{
public:
int RunTest()
{
std::cout << "Class Created. Perfect Running." << std::endl;
return 0;
}
};
SIM_OBJECT_CREATE_METHOD_REGISTER(CReflex);
int main(int argc, char **argv)
{
CReflex *pReflex = static_cast<CReflex *>(ClassFactory::GetInst().Create("CReflex"));
return pReflex->RunTest();
}
class_factory.h
#ifndef CLASS_FACTORY_H
#define CLASS_FACTORY_H
#include <string>
#include <iostream>
#include <unordered_map>
typedef void *(*CLASS_CREATE_FN)();
class ClassFactory
{
public:
static ClassFactory &GetInst();
public:
void *Create(const std::string &className);
void RegistClass(const std::string &className, CLASS_CREATE_FN fn);
private:
ClassFactory() = default;
~ClassFactory() = default;
ClassFactory(const ClassFactory &) = delete;
ClassFactory &operator=(const ClassFactory &) = delete;
private:
std::unordered_map<std::string, CLASS_CREATE_FN> m_mpObjName2Method;
};
class ClassRegisterAction
{
public:
ClassRegisterAction(const std::string &className, CLASS_CREATE_FN fn);
};
#define SIM_OBJECT_CREATE_METHOD_REGISTER(className) \
className *ClassCreate##className() \
{ \
return new (std::nothrow) className; \
} \
ClassRegisterAction g_ClassRegisterAction##className(#className, (CLASS_CREATE_FN)ClassCreate##className);
#endif // CLASS_FACTORY_H
class_factory.cpp
#include "class_factory.h"
/// Class ClassFactory
ClassFactory &ClassFactory::GetInst()
{
static ClassFactory factoryInst;
return factoryInst;
}
void *ClassFactory::Create(const std::string &className)
{
auto it = m_mpObjName2Method.find(className);
if (it == m_mpObjName2Method.end()) {
return nullptr;
} else {
return it->second();
}
}
void ClassFactory::RegistClass(const std::string &className, CLASS_CREATE_FN fn)
{
m_mpObjName2Method[className] = fn;
}
/// Class ClassRegisterAction
ClassRegisterAction::ClassRegisterAction(const std::string &className, CLASS_CREATE_FN fn)
{
ClassFactory::GetInst().RegistClass(className, fn);
}