C++设计模式 #7 工厂方法(Factory Method)
“对象创建”模式
- 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持创建的稳定。它是接口抽象之后的第一步工作。
动机
- 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
- 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免用户程序与这种“具体对象创建工作”的紧耦合?
举个栗子
我们思考C++设计模式 #4 观察者模式(Observer/Event)-CSDN博客中的文件分割的例子。对不同的文件我们可能有不同的分割策略。
class ISplitter {
public:virtual void split() = 0;virtual ~ISplitter(){}
};class TxtSplitter:public ISplitter{
public:void split(){cout << "this is a txt splitter" << endl;//...}
};class VideoSplitter:public ISplitter{
public:void split(){cout << "this is a video splitter" << endl;//...}
};
假设我们有一个button响应事件
void button_click(){//...ISplitter* txt_splitter = new TxtSplitter();//ISplitter* pic_splitter = new PictureSplitter();//ISplitter* video_splitter = new VideoSplitter();txt_splitter->split();//...}
问题
这样做虽然都是声明了一个虚基类的指针,但是还是依赖TxtSplitter这几个类的具体实现。也就是说我们这样不能绕开new的具体实现细节。

而且,如果我们的界面上只有一个与文件分割相关的按钮,就要在进行分割前进行大段的if-else判断,确定到底new哪个类型的文件分割器。这是一种相当低效且冗余的做法。
重构
class SplitterFactory{
public:virtual ISplitter* CreateSplitter() = 0;virtual ~SplitterFactory() {}
};class TxtSplitterFactory:public SplitterFactory{
public:ISplitter* CreateSplitter(){return new TxtSplitter();}
};class VideoSplitterFactory:public SplitterFactory{
public:ISplitter* CreateSplitter(){return new VideoSplitter();}
};
我们创建一个工厂虚基类SplitterFactory,将创建(new)具体splitter类的方式放在其子类中去实现。
现在我们再看button_click中是如何调用的
void button_click(SplitterFactory* factory){SplitterFactory* m_factory = factory;ISplitter* splitter = m_factory->CreateSplitter();splitter->split();
}
当然,m_factory这个工厂类的指针可以在button_click所属的类的成员变量中。调用buttoun_click时
TxtSplitterFactory* txtfactory = new TxtSplitterFactory();
VideoSplitterFactory* videofactory = new VideoSplitterFactory();
button_click(txtfactory);
button_click(videofactory);
以下是输出结果

8.工厂方法_哔哩哔哩_bilibili视频中是在button_click所属的类的构造函数中确定工厂指针,我个人感觉作为参数传递可能更容易理解。
工厂模式充分的利用了面向对象多态的性质,来保证了button_click函数中的稳定。
实际上,工厂模式并不能“消除”变化,而是将变化“驱赶”到了一处,也就是调用button_click之前。将变化集中起来处理,保证button与splitter之间结构的稳定。
理解C++多态对理解工厂模式很有必要。
模式定义
- 定义一个用于创建对象的接口(SplitterFactory),让子类决定实例化哪一个类。工厂模式使得一个类的实例化延迟到子类。 ——《设计模式》GoF
目的:解耦
手段:虚函数
结构

总结
- 工厂模式用于隔离类对象的使用者与具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
- 工厂模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好的解决了这种紧耦合关系。
- 工厂模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
相关文章:
C++设计模式 #7 工厂方法(Factory Method)
“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持创建的稳定。它是接口抽象之后的第一步工作。 动机 在软件系统中,经常面临着创…...
信息网络协议基础-接入网技术
文章目录 概述***基于ATM架构虚电路PVC和SVC信元格式为什么信元格式由AAL决定?网络架构传统电信网络:点对点链路PPP协议协议内容消息过程多协议封装功能电话网接入Internet(DSL 数字用户线路)主要接入技术ADSL关键技术DMTDSLAM体系结构PPPOE帧格式过程特点局域网定义参考模型L…...
springboot 自动装配原理
在理解springboot自动装配之前需要了解spring的Configuration原理和Conditional两个注解原理。可以看下以前写的这两篇文章 spring 源码阅读之Configuration解析 spring使用Conditional进行条件装配 spring的SPI机制之使用SpringFactoriesLoader加载服务实现 SpringBootApp…...
前端---表格标签
1. 表格的结构 表格是由行和列组成,好比一个excel文件 2. 表格标签 <table>标签:表示一个表格 <tr>标签:表示表格中的一行 <td>标签:表示表格中的列<th>标签:表示表格中的表头 示例代码: &l…...
【软件工程】可执行文件和数据分离
一、概述 可执行文件和数据分离是一种软件设计策略,旨在将程序代码和程序使用的数据分离存储。这种方法通常用于提高软件的模块化程度和灵活性,以及方便软件的管理和维护。 在可执行文件和数据分离中,程序代码通常以可执行文件的形式存储&a…...
Linux dirs命令
Linux dirs命令用于显示目录记录。 显示目录堆叠中的记录。 语法 dirs [/-n -l]参数: n 显示从左边算起第n笔的目录。-n 显示从右边算起第n笔的目录。-l 显示目录完整的记录。 实例 列出"/home/cc/Ruijie"里所有内容的详细信息。可用如下命令。 dir…...
有什么好用的C/C++源代码混淆工具?
有什么好用的C/C源代码混淆工具? 开始使用ipaguard 前言 iOS加固保护是直接针对ios ipa二进制文件的保护技术,可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP进行完整性保护,防止应用…...
iOS设备信息详解
文章目录 ID 体系iOS设备信息详解IDFA介绍特点IDFA新政前世今生获取方式 IDFV介绍获取方式 UUID介绍特点获取方式 UDID介绍获取方式 OpenUDID介绍 Bundle ID介绍分类其他 IP地址介绍获取方式 MAC地址介绍获取方式正常获取MAC地址获取对应Wi-Fi的MAC地址 系统版本获取方式 设备型…...
如何使用支付宝沙箱环境支付并公网调用sdk创建支付单服务
文章目录 1.测试环境2.本地配置2. 内网穿透2.1 下载安装cpolar内网穿透2.2 创建隧道3. 测试公网访问4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名5. 使用固定二级子域名进行访问 1.测试环境 MavenSpring bootJdk 1.8 2.本地配置 获取支付宝支付Java SDK,…...
[EFI]Dell Latitude-7400电脑 Hackintosh 黑苹果efi引导文件
硬件型号驱动情况主板 Dell Latitude-7400 处理器Intel Core i7-8665U已驱动内存16GB DDR4 RAM已驱动硬盘Toshiba KIOXIA 512GB SSD已驱动显卡Intel UHD 620 Graphics已驱动声卡Realtek ALC256已驱动有线网卡 无 无无线网卡蓝牙Intel Wireless-AC 9560已驱动 支持系统版本 maco…...
用芯片SIC8833可开发电子秤方案
SIC8833作为一款高性能的电子秤方案芯片,这款芯片是一个带24bitADC的8位RISC MCU,内置8k16位OTP程序存储器。具体24位双向I/O口的特性,广泛应用于电子衡器和精密测量及控制系统,能满足用户的不同需求和应用场景。 以下是电子秤方案…...
【Qt-QFile-QDir】
Qt编程指南 ■ Stream■ QTextStream■ QDataStream ■ QDial■ QDir■ QFile■■ ■ Stream ■ QTextStream /* 获取文件的路径 */ QString fileName QFileDialog::getOpenFileName(this);/* 指向文件 */ file.setFileName(fileName);/* 判断文件是否存在 */ if (!file.exi…...
设计模式之-单列设计模式,5种单例设计模式使用场景以及它们的优缺点
系列文章目录 设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列 设计模式之-单列设计模式,5种单例设计模式使用场景以及它们的优缺点 设计模式之-3种常见的工厂模式简单工厂模式、工厂方法模式和抽象工厂模式,每一种模式的概念、使用…...
Android 13 - Media框架(25)- OMXNodeInstance(二)
上一节我们了解了 OMXNodeInstance 的创建过程,以及 IOmx 服务和 OMXNodeInstance、OMX组件之间的联系。接下来我们将一起了解 ACodec 是如何通过 OMXNodeInstance 这个中间层进行端口定义设置,以及端口Buffer分配的。 OMXNodeInstance 的代码还是比较长…...
生物系统学中的进化树构建和分析R工具包V.PhyloMaker2的介绍和详细使用
V.PhyloMaker2是一个R语言的工具包,专门用于构建和分析生物系统学中的进化树(也称为系统发育树或phylogenetic tree)。以下是对V.PhyloMaker2的一些基本介绍和使用说明: 论文介绍:V.PhyloMaker2: An updated and enla…...
XStream 反序列化漏洞 CVE-2021-39144 已亲自复现
XStream 反序列化漏洞 CVE-2021-39144 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建 修复建议总结 漏洞名称 漏洞描述 在Unmarshalling Time处包含用于重新创建前一对象的类型信息。XStream基于这些类型的信息创建新实例。攻击者可以控制输入流并替换或注入对象&am…...
深入剖析LinkedList:揭秘底层原理
文章目录 一、 概述LinkedList1.1 LinkedList简介1.2 LinkedList的优点和缺点 二、 LinkedList数据结构分析2.1 Node节点结构体解析2.2 LinkedList实现了双向链表的原因2.3 LinkedList如何实现了链表的基本操作(增删改查)2.4 LinkedList的遍历方式 三、 …...
计算机网络复习-OSI TCP/IP 物理层
我膨胀了,挂我啊~ 作者简介: 每年都吐槽吉师网安奇怪的课程安排、全校正经学网络安全不超20人情景以及割韭菜企业合作的FW,今年是第一年。。 TCP/IP模型 先做两道题: TCP/IP协议模型由高层到低层分为哪几层: 这题…...
虚拟机服务器中了lockbit2.0/3.0勒索病毒怎么处理,数据恢复应对步骤
网络技术的不断发展也为网络威胁带来了安全隐患,近期,对于许多大型企业来说,许多企业的虚拟机服务器系统遭到了lockbit2.0/3.0勒索病毒攻击,导致企业所有计算机系统瘫痪,无法正常工作,严重影响了企业的正常…...
【MATLAB】 RGB和YCbCr互转
前言 在视频、图像处理领域经常会遇到不同色域图像的转换,比如RGB、YUV、YCbCr色域间的转换,这里提供一组转换公式,供大家参考。 色彩模型 RGB RGB色彩模型是一种用于表示数字图像的颜色空间,其中"RGB"代表红色&…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
