采用这种方式,有一个关键问题,便是在工厂中注册类名。我们的办法是针对于每一个类(Class),定义一个注册类(ClassReg),在注册类(ClassReg)的构造函数中注册此类(Class),然后再定义一个注册类的全局对象,在该全局对象初始化时,便会执行注册代码完成注册。
看到到这里懒人不乐意了,难道我们每写一个类,还要写一个相应的注册类?于是有人提出了使用宏来替换相应的代码,这样便大大减少了重复代码量。
采用宏当然可以,但是只能满足部分懒人。还有一部分人更懒,他们连使用这个宏完成注册都不想干,是呀,每写完一个类,还要在类后面使用宏来注册,这样确实还是比较麻烦。而且这样代码不够美观,也不便于维护,同时采用宏来转换类名,遇到命名空间,嵌套类,会非常麻烦,我们必须在注册的时候,把名字写全,比如REG_CLASS(MyNameSpace::MyClass::MyStruct)。
那么有没有更好的方法呢?当然有,我们可以用类模板来实现这种功能。设想这种方式,若我们要定义一个类MyClass,并且想让此类支持动态创建,那么我们只需这样定义即可class MyClass : public DynamicCreate<MyClass>{};。这样是不是清晰多了?下面请看代码:
DynamicFactory.h文件
[cpp] view plain copy print ? #ifndef __DYNAMIC_FACTORY_H__ #define __DYNAMIC_FACTORY_H__ #ifdef __GNUC__ #include <cxxabi.h> #endif #include <assert.h> #include <string.h> #include <stdlib.h> #include <map> #include <string> #include <typeinfo> // 动态对象基类 class DynamicObject { public: DynamicObject() {} virtual ~DynamicObject() {} }; // 动态对象创建工厂 class DynamicFactory { public: typedef DynamicObject* (*CreateFunction)(); static DynamicFactory & Instance() { static DynamicFactory fac; return fac; } // 解析类型名称(转换为 A::B::C 的形式) static std::string ReadTypeName(const char * name) { // 这里省略,具体代码在最后给出 ... } bool Regist(const char * name, CreateFunction func) { if (!func) { return false; } std::string type_name = ReadTypeName(name); return _create_function_map.insert(std::make_pair(type_name, func)).second; } DynamicObject * Create(const std::string & type_name) { if (type_name.empty()) { return NULL; } std::map<std::string, CreateFunction>::iterator it = _create_function_map.find(type_name); if (it == _create_function_map.end()) { return NULL; } return it->second(); } template<typename T> T * Create(const std::string & type_name) { DynamicObject * obj = Create(type_name); if (!obj) { return NULL; } T * real_obj = dynamic_cast<T*>(obj); if (!real_obj) { delete obj; return NULL; } return real_obj; } public: std::map<std::string, CreateFunction> _create_function_map; }; // 动态对象创建器 template<typename T> class DynamicCreate : public DynamicObject { public: static DynamicObject * CreateObject() { return new T(); } struct Registor { Registor() { if (!DynamicFactory::Instance().Regist(typeid(T).name(), CreateObject)) { assert(false); } } inline void do_nothing()const { } }; static Registor s_registor; public: DynamicCreate() { s_registor.do_nothing(); } virtual ~DynamicCreate() { s_registor.do_nothing(); } }; template <typename T> typename DynamicCreate<T>::Registor DynamicCreate<T>::s_registor; #endif #ifndef __DYNAMIC_FACTORY_H__ #define __DYNAMIC_FACTORY_H__ #ifdef __GNUC__ #include <cxxabi.h> #endif #include <assert.h> #include <string.h> #include <stdlib.h> #include <map> #include <string> #include <typeinfo> // 动态对象基类 class DynamicObject { public: DynamicObject() {} virtual ~DynamicObject() {} }; // 动态对象创建工厂 class DynamicFactory { public: typedef DynamicObject* (*CreateFunction)(); static DynamicFactory & Instance() { static DynamicFactory fac; return fac; } // 解析类型名称(转换为 A::B::C 的形式) static std::string ReadTypeName(const char * name) { // 这里省略,具体代码在最后给出 ... } bool Regist(const char * name, CreateFunction func) { if (!func) { return false; } std::string type_name = ReadTypeName(name); return _create_function_map.insert(std::make_pair(type_name, func)).second; } DynamicObject * Create(const std::string & type_name) { if (type_name.empty()) { return NULL; } std::map<std::string, CreateFunction>::iterator it = _create_function_map.find(type_name); if (it == _create_function_map.end()) { return NULL; } return it->second(); } template<typename T> T * Create(const std::string & type_name) { DynamicObject * obj = Create(type_name); if (!obj) { return NULL; } T * real_obj = dynamic_cast<T*>(obj); if (!real_obj) { delete obj; return NULL; } return real_obj; } public: std::map<std::string, CreateFunction> _create_function_map; }; // 动态对象创建器 template<typename T> class DynamicCreate : public DynamicObject { public: static DynamicObject * CreateObject() { return new T(); } struct Registor { Registor() { if (!DynamicFactory::Instance().Regist(typeid(T).name(), CreateObject)) { assert(false); } } inline void do_nothing()const { } }; static Registor s_registor; public: DynamicCreate() { s_registor.do_nothing(); } virtual ~DynamicCreate() { s_registor.do_nothing(); } }; template <typename T> typename DynamicCreate<T>::Registor DynamicCreate<T>::s_registor; #endif代码不多,就不做解释了。
测试代码mian.cpp
[cpp] view plain copy print ? #include <stdio.h> #include "DynamicFactory.h" class Test1 : public DynamicCreate<Test1> { public: // 注意:使用gcc,一定要显示申明构造函数,否则不会执行注册代码 Test1() {} }; namespace OK { struct Test2 : public DynamicCreate<Test2> { Test2() {} class Test3 : public DynamicCreate<Test3> { public: Test3() {} }; }; struct Test4 : public DynamicCreate<Test4> { Test4() {} }; } using namespace OK; //测试代码 int main() { Test1 * p1 = DynamicFactory::Instance().Create<Test1>("Test1"); printf("Create Test1 %s\n", (p1 ? "success" : "failure")); OK::Test2 * p2 = DynamicFactory::Instance().Create<OK::Test2>("OK::Test2"); printf("Create OK::Test2 %s\n", (p2 ? "success" : "failure")); OK::Test2::Test3 * p3 = DynamicFactory::Instance().Create<OK::Test2::Test3>("OK::Test2::Test3"); printf("Create OK::Test2::Test3 %s\n", (p3 ? "success" : "failure")); OK::Test4 * p4 = DynamicFactory::Instance().Create<OK::Test4>("OK::Test4"); printf("Create OK::Test4 %s\n", (p4 ? "success" : "failure")); return 0; } #include <stdio.h> #include "DynamicFactory.h" class Test1 : public DynamicCreate<Test1> { public: // 注意:使用gcc,一定要显示申明构造函数,否则不会执行注册代码 Test1() {} }; namespace OK { struct Test2 : public DynamicCreate<Test2> { Test2() {} class Test3 : public DynamicCreate<Test3> { public: Test3() {} }; }; struct Test4 : public DynamicCreate<Test4> { Test4() {} }; } using namespace OK; //测试代码 int main() { Test1 * p1 = DynamicFactory::Instance().Create<Test1>("Test1"); printf("Create Test1 %s\n", (p1 ? "success" : "failure")); OK::Test2 * p2 = DynamicFactory::Instance().Create<OK::Test2>("OK::Test2"); printf("Create OK::Test2 %s\n", (p2 ? "success" : "failure")); OK::Test2::Test3 * p3 = DynamicFactory::Instance().Create<OK::Test2::Test3>("OK::Test2::Test3"); printf("Create OK::Test2::Test3 %s\n", (p3 ? "success" : "failure")); OK::Test4 * p4 = DynamicFactory::Instance().Create<OK::Test4>("OK::Test4"); printf("Create OK::Test4 %s\n", (p4 ? "success" : "failure")); return 0; } 输出: [plain] view plain copy print ? [programmer@localhost test]$ ./test Create Test1 success Create OK::Test2 success Create OK::Test2::Test3 success Create OK::Test4 success [programmer@localhost test]$ ./test Create Test1 success Create OK::Test2 success Create OK::Test2::Test3 success Create OK::Test4 success下面给出上面省略的 ReadTypeName函数代码
[cpp] view plain copy print ? // 解析类型名称(转换为 A::B::C 的形式) // GCC 的type_info::name()输出的名称很猥琐,这里只做简单的解析,只支持自定义的结构体(非模板),类(非模板)、枚举、联合 static std::string ReadTypeName(const char * name) { #ifndef __GNUC__ const char * p = strstr(name, " "); if (p) { size_t prev_len = (size_t)(p - name); if (memcmp(name, "class", prev_len) == 0 || memcmp(name, "struct", prev_len) == 0 || memcmp(name, "enum", prev_len) == 0 || memcmp(name, "union", prev_len) == 0) { p += 1; return std::string(p); } } return std::string(name); #else char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr); std::string real_name_string(real_name); free(real_name); return real_name_string; #endif } // 解析类型名称(转换为 A::B::C 的形式) // GCC 的type_info::name()输出的名称很猥琐,这里只做简单的解析,只支持自定义的结构体(非模板),类(非模板)、枚举、联合 static std::string ReadTypeName(const char * name) { #ifndef __GNUC__ const char * p = strstr(name, " "); if (p) { size_t prev_len = (size_t)(p - name); if (memcmp(name, "class", prev_len) == 0 || memcmp(name, "struct", prev_len) == 0 || memcmp(name, "enum", prev_len) == 0 || memcmp(name, "union", prev_len) == 0) { p += 1; return std::string(p); } } return std::string(name); #else char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr); std::string real_name_string(real_name); free(real_name); return real_name_string; #endif }