每天一个设计模式之反射+工厂模式 Qt

  • A+
所属分类:IT技术

解决问题

使用工厂模式创建对象时,会通过传入的参数进行if判断,来创建出合适的对象。另外,也引入了实现子类,这样导致在工厂创建时,必须知道子类实现细节,并且,如果再增加子类,会需要修改工厂类,增加if判断。

达到目的

工厂通过传入类名字符串,创建出需要的对象。

代码

DynOBJ.h文件

  1. #ifndef DYNOBJ_H
  2. #define DYNOBJ_H
  3. #include <string>
  4. #include <map>
  5. typedef void* (*Constructor)();//定义一个函数指针void* Constructor()
  6. //该类负责创建一个map,该map负责存储类名字符串和其对应的构造方法,
  7. //并提供注册和根据类名字符串创建对象的方法
  8. class CObjecctFactory{
  9. public:
  10.     static void registerClass(std::string className, Constructor constructor){
  11.         constructors()[className] = constructor;
  12.     }
  13.     static void* createObject(const std::string& className){
  14.         Constructor constructor = NULL;
  15.         if(constructors().find(className) != constructors().end()){
  16.             constructor = constructors().find(className)->second;
  17.         }
  18.         if(!constructor)
  19.         {
  20.             return NULL;
  21.         }
  22.         return (*constructor)();//调用函数指针指向的函数,*即解引用
  23.     }
  24. private:
  25.     //<string,Constructor>:string->动态创建的类的类名,Constructor是构建函数指针
  26.     inline static std::map<std::string, Constructor>& constructors(){
  27.         static std::map<std::string, Constructor> instance;
  28.         return instance;
  29.     }
  30. };
  31. //定义一个宏,在新建类的地方调用,达到注册的目的
  32. #define REG_CLASS(class_name) \
  33. class class_name##Helper{ \
  34. public: \
  35.     class_name##Helper(){ \
  36.         CObjecctFactory::registerClass(#class_name,class_name##Helper::createObjFunc); \
  37.     } \
  38.     static void* createObjFunc(){ \
  39.         return new class_name; \
  40.     } \
  41. }; \
  42. class_name##Helper class_name##helper;
  43. //在这里直接实例化出每个类对应的全局对象helper,
  44. //自动调用helper的构造函数完成类注册
  45. #endif // DYNOBJ_H

该文件提供了注册类和创建对象的公共方法。

SimpleFactoryRefactor.cpp

  1. #include <iostream>
  2. #include <string>
  3. #include "DynOBJ.h"
  4. using namespace std;
  5. class Api{
  6. public:
  7.     virtual void test(string s)=0;
  8. protected:
  9.     Api(){}
  10. };
  11. class ImpleOne:public Api{
  12. public :
  13.     void test(string s){
  14.         cout<<"one is running"<<s;
  15.     }
  16. };
  17. REG_CLASS(ImpleOne)
  18. class ImpleTwo:public Api{
  19. public :
  20.     void test(string s){
  21.         cout<<"two is running"<<s;
  22.     }
  23. };
  24. REG_CLASS(ImpleTwo)//实际使用时,可以在子类定义的末尾使用注册宏
  25. class AutoFactory{
  26. public:
  27.     static Api* createApi(){
  28.         Api* pApi = NULL;
  29.         //可通过配置文件存储的字符串进行自动切换配置
  30.         //当然,如果应用在模块集成中,此处可以通过读取某个文件夹下的所有模块入口类名,
  31.         //在这里进行动态循环创建,再通过统一的接口Api进行无差别访问,不需要知道Api的子类实现
  32.         pApi = static_cast<Api*>(CObjecctFactory::createObject("ImpleOne"));
  33.         return pApi;
  34.     }
  35. };
  36. int main(void)
  37. {
  38.     Api* pApi = AutoFactory::createApi();
  39.     pApi->test(":AutoFactory");
  40.     system("pause");
  41.     return 0;
  42. }

 

Qt大课堂-QtShare

发表评论

您必须登录才能发表评论!