1. 适用场景
c++开发过程中使用工厂模式创建各种类对象的时候可能需要写一堆的’if-else’函数来根据传入的参数类型创建不同的类对象; 尤其是多态的情况下返回基类指针的情况. 例如:
class B -> class A // B继承A
class C -> class A // C继承AA *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);
}