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"代表红色&…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
