前言

我们知道Java/Python这种语言能够很好得 支持反射。反射机制 就是一种用户输入的字符串到对应实现方法的映射,比如http接口中 用户传入了url,我们需要调用该url对应的方法/函数对象 从而做出对应的操作。

而C++ 并没有友好得支持这样的操作,而最近工作中需要通过C++实现http接口,这个过程想要代码实现得优雅一些,就需要实现这样的功能。

最终的实现结果就是:

 int main() {Initial();JudgeName jm;auto res = jm.Judge("Zhang");res->ShowName();return 0;
}

我们只需要通过输入一个字符串,就能得到一个字符串对应的类的对象,从而调用该对象对应的方法。

实现过程

  1. 实现模版工厂
    反射机制本身是依赖工厂模式实现的,也就是提供一个创建函数对象的工厂,能够创建各种类型的函数对象。
    这里面的各种类型 – 其实就需要实现一个通用的模版工厂来达到创建各种类型的目的。

    // 工厂类模版,创建各种类型的类对象
    template <class OperationType_t>
    class OperationFactory {public:// 创建一个工厂单例,只会有一个对象工厂static OperationFactory<OperationType_t>& Instance() {static OperationFactory<OperationType_t> instance;return instance;}private:// We don't allow to constructor, copy constructor and align constructorOperationFactory() = default;~OperationFactory() = default;OperationFactory(const OperationFactory&) = delete;const OperationFactory& operator= (const OperationFactory&) = delete;};
    
  2. 实现类的对象到类名的映射。
    我们实现了能够创建所有类对象的函数工厂,但是还需要将创建好的对象和他们的类名字对应起来,做一个映射。
    在模版工厂类中补充映射逻辑:

    // Factory class template
    template <class OperationType_t>
    class OperationFactory {public:// Single pattern of the factorystatic OperationFactory<OperationType_t>& Instance() {static OperationFactory<OperationType_t> instance;return instance;}// 类名 和 类对象的映射void RegisterOperation(const std::string& op_name,OperationRegister<OperationType_t>* reg) {operationRegister[op_name] = reg;}// 获取指定类名字 对应的 对象// 也就是从映射map中查找OperationType_t* GetOperation(const std::string& op_name) {if (operationRegister.find(op_name) != operationRegister.end()) {return operationRegister[op_name]->CreateOperation(op_name);}return nullptr;}private:// We don't allow to constructor, copy constructor and align constructorOperationFactory() = default;~OperationFactory() = default;OperationFactory(const OperationFactory&) = delete;const OperationFactory& operator= (const OperationFactory&) = delete;// 类名字 和 类对象之间的映射std::map<std::string, OperationRegister<OperationType_t>* > operationRegister;
    };
    
  3. 实现一个注册类
    此时 我们通过这个注册类的入口 将类名 和类的对象完整映射起来。

    template <class OperationType_t>
    class OperationRegister {public:virtual OperationType_t* CreateOperation(const std::string& op_name) = 0;protected:OperationRegister() {}virtual ~OperationRegister() {}
    };// 注册一个以基类的子类对象。
    template <class OperationType_t, class OperationImpl_t>
    class OperationImplRegister : public OperationRegister<OperationType_t> {public:// 获取一个基类的工厂explicit OperationImplRegister(const std::string& op_name) {OperationFactory<OperationType_t>::Instance().RegisterOperation(op_name, this);}// 获取这个基类对应的子类对象OperationType_t* CreateOperation(const std::string& op_name) {return new OperationImpl_t(op_name);}
    };
    

应用

有了上面的模版工厂 以及 注册类名字 和 类的映射模版,接下来我们看看怎么使用:

我们实现了如下一个父类 以及 几个父类对应的子类实现

class Father {public:virtual std::string Name() = 0;virtual void ShowName() = 0;
};class Wang : public Father{public:Wang(const std::string& name) : name_(name){}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Zhang : public Father {public:Zhang(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Li : public Father {public:Li(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};

接下来需要统一注册一下这几个子类 的 名字 以及他们的对象:

// Construct the string name with there object's map
void Initial() {static bool init = false;if (init == false) {static OperationImplRegister<Father, Wang> wang("Wang");static OperationImplRegister<Father, Zhang> zhang("Zhang");static OperationImplRegister<Father, Li> li("Li");init = true;}
}

最后就是一个通过字符串 获取对象

class JudgeName {public:JudgeName(){}Father* Judge(const std::string& name) {OperationFactory<Father>& fac = OperationFactory<Father>::Instance();return fac.GetOperation(name);}
};

这个类的函数中,我们用户只需要传入一个字符串,就能够得到这个字符串的类的对象,从而进行后续的对象方法相关的操作。

能够极大得简化我们的if-else if 这样的分支代码,同时提升了代码的可扩展性。用户只需要继续补充想要使用的类,并将这个类的名字和对象注册到映射map中就好了,后续只需要使用类名就能够创建出这个类的对象。

完整代码实现

#include <iostream>
#include <map>using namespace std;// Register the operation
// The 'OperationTyple_t' is the abstract class
template <class OperationType_t>
class OperationRegister {public:virtual OperationType_t* CreateOperation(const std::string& op_name) = 0;protected:OperationRegister() {}virtual ~OperationRegister() {}
};// Factory class template
template <class OperationType_t>
class OperationFactory {public:// Single pattern of the factorystatic OperationFactory<OperationType_t>& Instance() {static OperationFactory<OperationType_t> instance;return instance;}void RegisterOperation(const std::string& op_name,OperationRegister<OperationType_t>* reg) {operationRegister[op_name] = reg;}OperationType_t* GetOperation(const std::string& op_name) {if (operationRegister.find(op_name) != operationRegister.end()) {return operationRegister[op_name]->CreateOperation(op_name);}return nullptr;}private:// We don't allow to constructor, copy constructor and align constructorOperationFactory() = default;~OperationFactory() = default;OperationFactory(const OperationFactory&) = delete;const OperationFactory& operator= (const OperationFactory&) = delete;std::map<std::string, OperationRegister<OperationType_t>* > operationRegister;
};// An template class to create the detail Operation
template <class OperationType_t, class OperationImpl_t>
class OperationImplRegister : public OperationRegister<OperationType_t> {public:explicit OperationImplRegister(const std::string& op_name) {OperationFactory<OperationType_t>::Instance().RegisterOperation(op_name, this);}OperationType_t* CreateOperation(const std::string& op_name) {return new OperationImpl_t(op_name);}
};class Father {public:virtual std::string Name() = 0;virtual void ShowName() = 0;
};class Wang : public Father{public:Wang(const std::string& name) : name_(name){}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Zhang : public Father {public:Zhang(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Li : public Father {public:Li(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};// Construct the string name with there object's map
void Initial() {static bool init = false;if (init == false) {static OperationImplRegister<Father, Wang> wang("Wang");static OperationImplRegister<Father, Zhang> zhang("Zhang");static OperationImplRegister<Father, Li> li("Li");init = true;}
}class JudgeName {public:JudgeName(){}Father* Judge(const std::string& name) {OperationFactory<Father>& fac = OperationFactory<Father>::Instance();return fac.GetOperation(name);}
};int main() {Initial();JudgeName jm;auto res = jm.Judge("Zhang");res->ShowName();return 0;
}

C++ 通过模版工厂实现 简单反射机制相关推荐

  1. java 反射 工厂模式_Java反射机制demo(七)—反射机制与工厂模式

    Java反射机制demo(七)-反射机制与工厂模式 工厂模式 简介 工厂模式是最常用的实例化对象模式. 工厂模式的主要作用就是使用工厂方法代替new操作. 为什么要使用工厂模式?直接new不好吗? 直 ...

  2. 解析Spring IOC原理——工厂模式与反射机制的综合应用

    (一)工厂模式 从一个例子开始讲起: 首先我们建立一个Chinese.java类,该类的sayHelloWorld(String name)方法,用中文对名为name的人问好,其内容如下: [java ...

  3. java 反射 工厂_JAVA反射机制、工厂模式与SPRING IOC

    ABSTRACT Spring的IOC(控制反转)是Spring框架的灵魂,有了它才有了Spring的很多其他的灵活的特性.使用 Spring 开发项目时,控制层.业务层.DAO 层都是通过 IoC ...

  4. Java反射机制与工厂模式

    工厂模式 简介 工厂模式是最常用的实例化对象模式. 工厂模式的主要作用就是使用工厂方法代替new操作. 为什么要使用工厂模式?直接new不好吗? 直接new没有什么不好,只是工厂模式可以给系统带来更好 ...

  5. blg-017-在中C++用全局对象的构造函数实现反射机制

    在C++中利用全局对象的构造函数实现反射机制 在C++中利用全局对象的构造函数实现反射机制 1. 反射机制 2. 方法概述 3. 引入反射机制的简单工厂模式 3.1 工厂类 3.1.1 a_facto ...

  6. 秒懂系列,深入理解Java反射机制

    文章目录 深入理解Java反射机制 一.Java反射概述 二.Java创建对象思想传递 三.类对象 3.1 类对象和类的对象 3.2 三种获取类对象的方法 四.Class对象的常用方法 4.1 获取成 ...

  7. 微盘java 反射原理图_Java 从入门到精通-反射机制

    导读 Java反射机制是开发者迈向结构化开发的重要一步,同时掌握了反射机制也就掌握了所有框架的核心实现思想. 认识反射机制 简单例子 通过以上的程序就会发现,除了对象的正向处理操作之外,还可以通过ge ...

  8. [转]Java反射机制详解

    目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详 ...

  9. Java基础——Java反射机制及IoC原理

    一.概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通过反射机制 ...

最新文章

  1. 使用centos6.6部署Cobbler--自动安装centos系统
  2. tidb 企业_TiDB 在马上消费金融核心账务系统归档及跑批业务下的实践
  3. 【MySQL】深入浅出剖析mysql事务锁机制 - 笔记
  4. 二级联动菜单ajax刷新,jquery json ajax 二级联动菜单实例
  5. Desert King POJ - 2728
  6. 关于Android错误 View requires API level 14 (current...
  7. 计算机系统-记录Bochs调试器几个常用命令
  8. python分割压缩_Python读取分割压缩TXT文本文件实例
  9. anaconda升级sklearn版本
  10. 浪潮存储进逼国际一线厂商
  11. mysql5.6怎样测试_Mysql5.6 字符集设置测试
  12. 已知两个向量的坐标求夹角的大小_两个向量的夹角怎么算
  13. 台式计算机怎么连接蓝牙 win10,win10台式电脑蓝牙怎么开启(开启电脑蓝牙的步骤图)...
  14. HashMap是怎样实现快速查找的
  15. LA 5713 秦始皇修路
  16. 2022.12.14 英语背诵
  17. Skleran-线性模型-最小角回归(LARS)
  18. spark+smack+openfire实现请求响应简单流程
  19. BIOS 报警声 / 声音提示
  20. 【sql随笔】sql题目:查询每班成绩前三名

热门文章

  1. 43.放苹果(递归练习)
  2. 屏蔽浏览器默认样式 user agent stylesheet
  3. java 常用正则表达式
  4. [原]SSL 开发简述(Delphi)
  5. ASP.NET 2.0 ajax中gridView的刷新问题!
  6. ORB-SLAM2系统的实时点云地图构建
  7. 大一计算机在线考试,Word 大一计算机考试操作题
  8. java实时获取android网速_获取Android网速的另一种方法
  9. java中separator_java - File.separator和路径中的斜杠之间的区别
  10. 一键部署dns服务_OpenShift : 通往云原生、DevOps、微服务和Serverless的大门