之前在代码重构书中有了解过java中的反射机制可以消除switch-case,详情可以参考这篇博客http://blog.csdn.net/wwh578867817/article/details/49309789。那么我们的C++有没有类似干掉switch-case的方法?

1原始的工厂是如何创建派生类对象的

假如我们有个基类为Father,它有好多继承类分别为Son1,Son2,…
那么我们原始工厂(用来创建其子类对象)方法也就是用switch-case来实现
伪代码如下

Message* create(int type)
{switch (type) {case _Son1_:m = new Son1;break;case _Son2_:m = new Son2;break;case _Son3_:m = new Son3;break;case _Son4_:m = new Son4;break;case __Son5:m = new Son5;break;default:break;}
}

如果我们的case语句少点还好,一旦有好多的case语句,我们的代码维护起来就会变得很麻烦,那么我们有什么办法可以像java的反射机制一样干掉常常的switch-case语句呢?

2.自动注册的对象工厂

没错我们可以实现一个有自动注册功能的对象工厂就可以干掉switch-case了

为什么其可以干掉switch-case?

首先我们的自动注册对象工厂会维护一个map集合,该map的key便是我们上述的switch-case里的type,value为一个可调用对象,该可调用对象会调用具体某个Son类的构造函数,然后返回新生成对象的额指针。在每个子类的头文件中,我们就会将该子类的type和对应的可调用对象插入到map中,这样当我们程序中要生成某个具体子类对象时,我们的工厂便会更具type找到map中对应的可调用对象,然后执行可调用对象便可生成该type所对应的类对象了

具体实现如下

我们把父类看做基础消息,命名为Message,继承其的消息分别为Message2…等
父类代码

#pragma onceclass Message
{public:virtual ~Message(){}virtual void foo()//由子类自己实现的接口{}
};

工厂类的代码实现

#pragma once#include <map>
#include <string>
#include <functional>
#include <memory>
#include "message.h"class Factory
{public:template<typename T>struct Register //用于将特定构造函数的可调用对象插入map的注册类{Register(const std::string &key){Factory::get().map_.emplace(key,[]{return new T();});//lambda表达式作为可调用对象       }template<typename... Args>//构造函数为有参数时Register(const std::string &key,Args... args){Factory::get().map_.emplace(key,[&]{return new T(args...);});}};static Message *produce(const std::string &key)//生产具体的对象{if(map_.find(key) == map_.end()){throw std::invalid_argument("the message key is not exist!");}return map_[key](); //注意lambda在这里执行}//用智能指针来管理裸指针static std::unique_ptr<Message> produce_unique(const std::string &key){return std::unique_ptr<Message>(produce(key));}static std::shared_ptr<Message> produce_shared(const std::string &key){return std::shared_ptr<Message>(produce(key));}private:Factory(){};Factory(const Factory&) = delete;Factory(Factory &&) = delete;static Factory &get()//每次返回静态局部变量多额引用可轻松实现类的单例模式{static Factory instance;return instance;}static std::map<std::string,std::function<Message *(void)>> map_;   //保存type和可调用对象的map
};std::map<std::string,std::function<Message *()>> Factory::map_;#define REGISTER_MESSAGE_VNAME(T) reg_msg_##T##_
#define REGISTER_MESSAGE(T,key, ...) static Factory::Register<T> REGISTER_MESSAGE_VNAME(T)(key,##__VA_ARGS__)

类Message1的代码

#pragma once#include "message.h"
#include "factory.h"
#include <iostream>class Message1 : public Message
{public:Message1(){std::cout << "Message1" << std::endl;}~Message1(){}void foo()override  //自己实现的接口{std::cout << "Message1" << std::endl;}
};REGISTER_MESSAGE(Message1,"Message1");//通过此将执行Message1构造函数的可调用对象插入到map中

类Message2的代码

#pragma once#include "message.h"
#include "factory.h"
#include <iostream>class Message2 : public Message
{public:Message2(){std::cout << "Message2" << std::endl;}Message2(int a){std::cout<< "Message2" <<std::endl;}~Message2(){}void foo()override{std::cout << "Message2" << std::endl;}
};

测试程序的代码


#include "message1.h"
#include "message2.h"
#include "message.h"int main(int argc,char **argv)
{Message *p = Factory::produce("Message1");Message *p1 = Factory::produce("Message2");p->foo();p1->foo();delete p;delete p1;return 0;
}

执行结果为

这样我们就可以用自动注册工厂神奇的消灭掉switch-case了
详细代码请到https://github.com/Miaoshuai/factory

自动注册工厂消灭switch-case相关推荐

  1. 三步实现自动注册工厂替代switch语句(c++)

    概述 在学长博客里看到了使用自动注册工厂替代switch语句的文章,想到可以将其用到自己的项目里,就照猫画虎学习着也实现了一个. 这里并不是用其替代创建派生类的传统Factory,而是为了替代服务器中 ...

  2. 基于模板的自动注册工厂模式(C++11实现)

    工厂类 factory.h #pragma once#include <functional> #include <memory> #include <unordered ...

  3. 用C++实现一个自动注册的工厂

    原文地址:http://geek.csdn.net/news/detail/48963 工厂方法是最简单地创建派生类对象的方法,也是很常用的,工厂方法内部使用switch-case根据不同的key去创 ...

  4. C++中实现自动注册的工厂

    很长时间没有更新博客了,不是博主懒,是因为博主在帮研究生妹子弄硕士论文,定位方面的,被imu,行人航迹,激光匹配各种虐,不说了,都是泪. Factory模式,在工程中多用了创建派生类实例,内部一般使用 ...

  5. c++11实现一个自动注册的工厂模式

    实现动机 最近项目中需要用到工厂模式,但是普通的工厂模式面临一个问题,每新增一个派生类,都需要在工厂中加一个case分支,这样就会频繁地修改工厂的代码,而且随着派生类越来越多,case分支也逐渐增多, ...

  6. C++11实现一个自动注册的工厂

    转自:https://www.cnblogs.com/qicosmos/p/5090159.html 实现动机 工厂方法是最简单地创建派生类对象的方法,也是很常用的,工厂方法内部使用switch-ca ...

  7. 工厂模式之消除switch/case语句

    2019独角兽企业重金招聘Python工程师标准>>> 我们在平时的编码中,我们经常会遇到这样的情况: 使用过多的switch/case 或者 if else 语句,非常不爽,也违背 ...

  8. ARouter init 源码解析(自动注册的实现)

    概要 使用ARouter,我们只需要在必要的地方加上注解,然后在application中init Arouter就可以直接通过代码进行路由跳转了. 为什么我们可以不用写任何注册的代码,就直接跳转到相关 ...

  9. 微信扫码 - 关注公众号后网站自动注册并登录的实现

    微信扫码 - 关注公众号后网站自动注册并登录的实现 需求描述 在自己网站上点击微信登录,网站自己弹出一个二维码.扫描二维码后弹出公众号的关注界面.只要一关注公众号网站自动登录.第二次扫描登录的时候网站 ...

最新文章

  1. LruCache缓存机制
  2. strstr(),strchr()
  3. Linux中设置定期备份oracle数据库
  4. ZigBee On Windows Mobile—利用CF卡接口外扩
  5. oracle索引总结
  6. 【java读书笔记】——java的异常处理
  7. [css] 写出主流浏览器内核私有属性的css前缀
  8. CVPR2021 用更好的目标检测器提取视觉特征!微软提出VinVL,基于更好的视觉特征,达到更强的多模态性能...
  9. 算法(第4版) Chapter 5.2 单词查找树
  10. Java基础——枚举类的使用教程
  11. 5G(4)---5G 标准
  12. 微软的基础服务器,微服务器当道 微软云端基础构架揭秘
  13. mysql小结果集驱动大结果集_具体优化查询语句的指导原则小结果集驱动大结果集避免子查询...
  14. 判断年月日是否正确及获取当前天的前一天或前一个月
  15. CentOS 7.4安装postgresql96
  16. 嵌入式Linux系统驱动hp1020打印机
  17. vue 下载pdf文件
  18. 05_经典电影台词(一)
  19. 金山WPS计算机视觉算法工程师
  20. 一年风雨几度寒,一杯浊酒敬虎年

热门文章

  1. python-scrapy爬虫框架爬取王者荣耀英雄皮肤图片和技能信息
  2. 在SQuAD2.0榜单上出现过的部分模型详解StructBert,T5,RoBERTa,RetroReader,ALBert
  3. Redis Java客户端的选择
  4. Jbrowse中的BigWig Tracks配置
  5. 问题 F: 寻找预言家
  6. 后台和用户跟踪要点_联系人跟踪应用程序的一些基本要点
  7. java读取execle
  8. 三维建模软件的插件安装教程——3D Max
  9. Chamfer Distance--倒角距离
  10. 小程序获取上一页的数据修改上一个页面的数据