工厂模式——工厂方法模式+注册表
工厂方法模式的瑕疵
在前一篇笔记中我们介绍了工厂方法模式,示例的类图如下:

考虑一种情况:现在要在程序运行时,根据外部资源,动态的实例化对象。也就是说在编译期我们无法知道要实例化的对象的类型。因此在实例化的过程中,就需要加以判断。
例如,在我的例子中,要根据连接到主机的相机来实例化相机对象,那么客户端(使用工厂方法创建实例的一方)使用工厂方法模式创建对象的时候,代码可能是这样:
//运行时确定数组大小,且确定后不可改变
auto camera_devices_ = std::make_unique<std::shared_ptr<CameraDevice>[]>(onlined_camera_num_);for(int i = 0; i < onlined_camera_num_; ++i)
{std::shared_ptr<CameraDeviceFactory> factory;if("Sick" == camera_name[i]) //camera_name[i]中元素是提前获取的与连接的相机对应的供应商名称factory = std::make_shared<SickCameraFactory>();else if("Basler" == camera_name[i])factory = std::make_shared<BaslerCameraFactory>();else if("Huaray" == camera_name[i])factory = std::make_shared<HuarayCameraFactory>();camera_devices_[i] = factory->CreateCamera();
}
虽然工厂方法模式遵循了开闭原则,即当有新类型的时候,无需修改现有的代码,只需新加产品类和对应工厂类即可。但是对于客户端来说,当需要实例化的类型数量增加时,就需要新增else if去适配,这使得客户端代码变得冗长且难以维护。
注册表
为了解决上面问题,我们可以实现一个类型的注册表,允许动态创建对象。这种方法通过将关键字映射到构造函数指针,使得可以根据字符串名称动态地实例化对象。
#ifndef Reflection_H
#define Reflection_H#include <map>
#include <string>template <typename T, typename... ArgType>
void* CreateInstance(ArgType... args)
{return new T(args...);
}//需要反射的类使用该宏注册
#ifndef ReflectRegister
#define ReflectRegister(identifier, class_name, ...) \static bool __type##class_name = Object::Register(identifier, (void*)CreateInstance<class_name, ##__VA_ARGS__>);
#endifclass Object
{
public:template <typename BaseClass, typename... ArgType>static BaseClass *CreateObject(const std::string &vendor_name, ArgType... args){using CreateFactory = BaseClass *(*)(ArgType...);auto& class_map = GetStaticFuncMap();auto iter = class_map.find(vendor_name);if (iter == class_map.end()){CRRC_ERROR("class_name not found in map");return nullptr;}else{CRRC_DEBUG("class_name found in map");return reinterpret_cast<CreateFactory>(class_map[vendor_name])(args...);}} //向map中注册关键字和类的构造函数static bool Register(const std::string &vendor_name, void *ctor_ptr){CRRC_DEBUG("Register class_name:"<<vendor_name);GetStaticFuncMap()[vendor_name] = ctor_ptr;return true;}private://获取全局唯一的map//map记录了关键字和类的构造函数的映射关系static std::map<std::string, void*>& GetStaticFuncMap(){static std::map<std::string, void*> class_map_;return class_map_;}};#endif //Reflection_H
在具体相机工厂中,我们可以使用ReflectRegister注册此类(以Basler相机为例,其余类似):
class BaslerCameraDeviceFactory : public CameraDeviceFactory
{
public:std::shared_ptr<CameraDevice> CreateCameraDevice() override{return std::make_shared<BaslerCameraDevice>();}
};ReflectRegister("Basler", BaslerCameraDeviceFactory);
好了,现在回头再看客户端使用工厂方法模式创建对象的代码,就可以简化为:
//运行时确定数组大小,且确定后不可改变
auto camera_devices_ = std::make_unique<std::shared_ptr<CameraDevice>[]>(onlined_camera_num_);for(int i = 0; i < onlined_camera_num_; ++i)
{auto p_factory = Object::CreateObject<CameraDeviceFactory>(camera_name[i]);//camera_name[i]中元素是提前获取的与连接的相机对应的供应商名称if (!p_factory)continue;elsecamera_devices_[i] = p_factory->CreateCameraDevice();delete p_factory;
}
文章转载自:paw5zx
原文链接:https://www.cnblogs.com/paw5zx/p/18229334
体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构
相关文章:
工厂模式——工厂方法模式+注册表
工厂方法模式的瑕疵 在前一篇笔记中我们介绍了工厂方法模式,示例的类图如下: 考虑一种情况:现在要在程序运行时,根据外部资源,动态的实例化对象。也就是说在编译期我们无法知道要实例化的对象的类型。因此在实例化的过…...
实验一、网络传输介质————双绞线 《计算机网络》
蝙蝠身上长鸡毛,忘了自己是什么鸟。 目录 一、实验目的 二、实验内容 1.双绞线的原理以及分类 2.了解双绞线的性质、结构与特性 3.掌握双绞线的制作方法 4.了解双绞线的材质 5.了解双绞线的发展趋势 三、实验小结 一、实验目的 1.双绞线的原理以及分类 2.了…...
在Linux/Ubuntu/Debian中使用lshw查看系统信息
在Linux/Ubuntu/Debian中使用lshw查看系统信息 lshw 是一个用于显示硬件配置的命令,可以提供系统硬件的详细信息,包括 CPU、内存、硬盘、主板等。该命令需要超级用户权限来获取详细信息。 常见用法: 显示所有硬件信息: sudo l…...
提高篇(八):扩展Processing功能:从库使用到跨平台应用
提高篇(八):扩展Processing功能:从库使用到跨平台应用 引言 Processing是一款强大的创意编程工具,广泛应用于艺术、设计和教育等领域。但其真正的魅力在于其可扩展性:你可以通过使用各种扩展库、结合其他编程语言、在不同硬件平台上应用,甚至创建自己的扩展库来丰富Pro…...
ubuntu18.04环境下,arduino ide在打开串口监视器时报错
ubuntu18.04环境下,arduino ide在打开串口监视器时报错 Exception in thread “AWT-EventQueue-0” java.lang.UnsatisfiedLinkError: /home/lzx/.jssc/linux/libjSSC-2.8_x86_64.so: /home/lzx/.jssc/linux/libjSSC-2.8_x86_64.so: file too short 这个错误表明 li…...
码蹄集部分题目(2024OJ赛18期;并查集+ST表+贪心)
1🐋🐋史莱姆融合(钻石;并查集) 时间限制:1秒 占用内存:128M 🐟题目描述 🐟题目思路 这道题目使用并查集,同一集合的所有元素的最顶上的祖父节点是统一的。…...
算法:前缀和题目练习
目录 题目一:一维前缀和[模版] 题目二:二维前缀和[模版] 题目三:寻找数组的中心下标 题目四:除自身以外数组的乘积 题目五:和为K的子数组 题目六:和可被K整除的子数组 题目七:连续数组 题…...
记录项目使用ts时引入js文件后导致项目运行空白问题
主要原因: 使用ts后开启了eslint检测,而js压缩文件引入的位置在eslint检测的文件内。导致eslint检测认为该文件为很大的文件,或eslint认为此文件内存在无法处理的语法结构等问题。 解决方法: 1、把文件移到eslint检测外的文件引入…...
Kafka消费者api编写教程
1.基本属性配置 输入new Properties().var 回车 //创建属性Properties properties new Properties();//连接集群properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"node1:9092,node2:9092");//反序列化properties.put(ConsumerConfig.KEY_DESERIALIZER_CL…...
什么情况下要配置DNS服务
什么是DNS 一、DNS就是域名解析 我们上网的方式通常都由ip地址组成,但是为了有个规范,而且我们也不可能去记住那么多一串Ip数字,首先域名就会比ip好记很多,其次固定性,一旦服务器换了,只要重新绑定域名对…...
华为端云一体化开发 (起步1.0)(HarmonyOS学习第七课)
官方文献: 为丰富HarmonyOS对云端开发的支持、实现端云联动,DevEco Studio推出了云开发功能,开发者在创建工程时选择云开发模板,即可在DevEco Studio内同时完成HarmonyOS应用/元服务的端侧与云侧开发,体验端云一体化协…...
数据结构之ArrayList与顺序表(上)
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 顺序表的学习,点我 上面这篇博文是关于顺序表的基础知识,以及顺序表的实现。…...
Java 8 中的 Stream API,用于处理集合数据
Java 8 引入了 Stream API,使得处理集合数据变得更加简洁和高效。Stream API 允许开发者以声明式编程风格操作数据集合,而不是使用传统的迭代和条件语句。 一、基本概念 1.1 什么是 Stream Stream 是 Java 8 中的一个新抽象,它允许对集合数…...
106、python-第四阶段-3-设计模式-单例模式
不是单例类,如下: class StrTools():pass str1StrTools() str2StrTools() print(str1) print(str2) 运用单例,先创建一个test.py class StrTools():pass str1StrTools()然后创建一个hello.py,在这个文件中引用test.py中的对象&a…...
【猫狗识别系统】图像识别Python+TensorFlow+卷积神经网络算法+人工智能深度学习
猫狗识别系统。通过TensorFlow搭建MobileNetV2轻量级卷积神经算法网络模型,通过对猫狗的图片数据集进行训练,得到一个进度较高的H5格式的模型文件。然后使用Django框架搭建了一个Web网页端可视化操作界面。实现用户上传一张图片识别其名称。 一、前言 …...
记录汇川:红绿灯与HMI-ST
项目要求: 子程序: 子程序: 实际动作如下: 红绿灯与HMI-ST...
已解决java.nio.charset.CoderMalfunctionError: 编码器故障错误的正确解决方法,亲测有效!!!
已解决java.nio.charset.CoderMalfunctionError: 编码器故障错误的正确解决方法,亲测有效!!! 亲测有效 报错问题解决思路解决方法1. 检查和清理输入数据2. 选择正确的字符集3. 处理异常情况4. 更新Java版本或库5. 检查第三方库的依…...
Linux 中常用的设置、工具和操作
1.设置固定的ip地址步骤 1.1 添加IPADDR“所设置的固定ip地址” TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no" BOOTPROTO"static" DEFROUTE"yes" IPV4_FAILURE_FATAL"no" IPV6INIT"yes" IPV6…...
[论文笔记]AIOS: LLM Agent Operating System
引言 这是一篇有意思的论文AIOS: LLM Agent Operating System,把LLM智能体(代理)看成是操作系统。 基于大语言模型(LLMs)的智能代理的集成和部署过程中存在着许多挑战,其中问题包括代理请求在LLM上的次优调度和资源分配,代理和LLM之间在交互…...
2024全国高考作文题解读(文心一言 4.0版本)
新课标I卷 阅读下面的材料,根据要求写作。(60分) 随着互联网的普及、人工智能的应用,越来越多的问题能很快得到答案。那么,我们的问题是否会越来越少? 以上材料引发了你怎样的联想和思考?请写…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
