C++设计模式-抽象工厂模式:从原理、适用场景、使用方法,常见问题和解决方案深度解析
一、模式基本概念
1.1 定义与核心思想
抽象工厂模式(Abstract Factory Pattern)是创建型设计模式的集大成者,它通过提供统一的接口来创建多个相互关联或依赖的对象族,而无需指定具体类。其核心思想体现在两个维度:
- 横向扩展:能生产同一产品族的多个关联对象(如汽车工厂同时生产发动机和变速箱)
- 纵向兼容:支持不同产品族的实现替换(如Windows/Mac两种风格的UI控件套件)
1.2 与相关模式对比
例如:游戏装备系统采用抽象工厂模式,可批量生成战士的剑盾套装或法师的法杖长袍组合。
二、内部实现原理
2.1 运行机制解析
- 接口抽象层:定义产品族的创建接口(如ICarFactory包含CreateEngine和CreateTransmission)
- 具体实现层:针对不同产品族实现具体工厂(如BenzFactory生产涡轮增压发动机+9AT变速箱)
- 客户端调用:通过配置选择工厂类型,获得完整产品组合。
2.2 设计原则体现
- 开闭原则:新增产品族无需修改已有代码(如新增新能源车系)
- 依赖倒置:客户端依赖抽象接口而非具体类
- 接口隔离:每个工厂接口仅聚焦特定产品族创建
三、适用场景分析
3.1 典型应用领域
-
跨平台系统开发
Windows/Mac/Linux三套UI控件(按钮/文本框/滚动条)的自动适配。 -
多规格产品体系
汽车制造中燃油车与电动车不同动力系统的配套生产 -
游戏对象生成
按职业生成配套装备(战士:重甲+大剑;盗贼:皮甲+匕首) -
数据库访问层
统一接口支持MySQL/Oracle/SQLite的Connection+Command组合
3.2 适用性判断标准
符合以下三个条件时优先选择抽象工厂模式:
系统需要处理多个关联产品的创建
产品族之间存在明确的组合约束
需要屏蔽具体产品实现的细节差异
四、实现方法与最佳实践
4.1 标准实现步骤
定义抽象产品接口
class IEngine {
public:virtual void Start() = 0;
};class ITransmission {
public:virtual void Shift() = 0;
};
创建具体产品实现
class TurboEngine : public IEngine { /*...*/ };
class ElectricMotor : public IEngine { /*...*/ };
构建抽象工厂接口
class ICarFactory {
public:virtual IEngine* CreateEngine() = 0;virtual ITransmission* CreateTransmission() = 0;
};
实现具体工厂类
class SportsCarFactory : public ICarFactory {// 生产涡轮增压引擎+双离合变速箱
};
4.2 现代C++增强实现
智能指针集成
std::unique_ptr<IEngine> CreateEngine() {return std::make_unique<TurboEngine>();
}
模板元编程优化
template<typename EngineType, typename TransmissionType>
class GenericCarFactory : public ICarFactory {// 通用实现减少重复代码
};
C++20概念约束
template<typename T>
concept CarFactory = requires {{ T::CreateEngine() } -> std::derived_from<IEngine>;{ T::CreateTransmission() } -> std::derived_from<ITransmission>;
};
五、常见问题与解决方案
5.1 产品族扩展难题
问题现象:新增产品类型需修改所有工厂接口(如增加车载电脑模块)
解决方案:
采用桥接模式分离产品维度
定义扩展点接口实现渐进式升级
5.2 工厂类膨胀问题
典型场景:支持10个平台导致工厂类数量爆炸
优化策略:
引入参数化工厂模式
使用类型注册表动态创建工厂
5.3 循环依赖困境
产生原因:产品之间相互引用(如发动机依赖变速箱参数)
解决途径:
引入中介者对象协调创建过程
采用两阶段初始化策略
5.4 多线程安全问题
风险场景:并发环境下工厂实例被重复创建
防护机制:
std::mutex factory_mutex;ICarFactory* GetFactory() {std::lock_guard<std::mutex> lock(factory_mutex);// 双检锁确保单例安全
}
六、高级应用场景
6.1 动态配置系统
结合JSON配置文件实现运行时工厂切换:
{"car_type": "electric","components": {"engine": "300kW_motor","transmission": "single_speed"}
}
6.2 混合模式创新
抽象工厂+建造者模式
工厂负责选择产品族,建造者处理复杂装配流程
抽象工厂+策略模式
根据性能需求动态切换动力组合(经济型/运动型)
6.3 分布式对象创建
通过RPC机制实现跨网络的工厂调用:
RemoteFactoryProxy factory("tcp://10.0.0.1:8080");
auto engine = factory.CreateEngine(); // 远程创建对象
七、行业实践案例
7.1 跨平台渲染引擎
需求背景:支持DirectX/Vulkan/Metal三种图形API
实现方案:
定义RenderDevice、CommandBuffer等抽象接口
为每个API实现具体工厂(DXFactory/VKFactory等)
启动时根据系统环境自动选择工厂
7.2 金融交易系统
业务需求:支持FIX/FAST/SBE多种协议格式
设计要点:
抽象工厂生产协议解析器+编码器组合
通过消息头自动选择协议工厂
异常处理工厂保证协议容错
本篇系统阐述了抽象工厂模式的理论体系和实践方法,结合一些协议处理案例和跨平台实现方案,为大家提供了从基础认知到高阶应用的全方位说明。可以在实际开发中,根据具体业务场景灵活运用文中的解决方案,逐步构建可维护、易扩展的软件系统。
相关文章:
C++设计模式-抽象工厂模式:从原理、适用场景、使用方法,常见问题和解决方案深度解析
一、模式基本概念 1.1 定义与核心思想 抽象工厂模式(Abstract Factory Pattern)是创建型设计模式的集大成者,它通过提供统一的接口来创建多个相互关联或依赖的对象族,而无需指定具体类。其核心思想体现在两个维度: …...
LINUX系统安装+添加共享目录
一、前言 Windows或mac系统中创建Linux工作环境是基于VMware和SL(Scientific Linux),下面分别安装二者。 二、VMware软件安装及注册 1、双击VMware安装包 2、点击下一步 3、 勾选接受许可,并点击下一步 4、更改路径(建议更改为容易找到的路…...
《UE5_C++多人TPS完整教程》学习笔记34 ——《P35 网络角色(Network Role)》
本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P35 网络角色(Network Role)》 的学习笔记,该系列教学视频为计算机工程师、程序员、游戏开发者、作家(Engineer, Programmer, Game Developer, Author) Stephe…...
成为git砖家(9): rebase进阶: 拆分commit为多个
问题描述 当一次性 git add 了多个修改点, 并且快速的执行了 git commit 后, 你觉得有点懊恼: 明明可以独立为两次或多次 commit, 揉在一块导致历史记录不太清晰。 比如我在 nn1 这个练手项目中, 最近一次 commit&am…...
pytorch retain_grad vs requires_grad
requires_grad大家都挺熟悉的,因此穿插在retain_grad的例子里进行捎带讲解就行。下面看一个代码片段: import torch# 创建一个标量 tensor,并开启梯度计算 x torch.tensor(2.0, requires_gradTrue)# 中间计算:y 依赖于 x&#x…...
Axure常用变量及使用方法详解
点击下载《Axure常用变量及使用方法详解.pdf》 摘要 Axure RP 作为一款领先的前端原型设计工具,提供了全面的 变量 和 函数 系统,以支持复杂的交互设计和动态内容展示。本文将从专业角度详细解析 Axure 中的 全局变量、中继器数据集变量/函数、元件变量…...
为企业级AI交互系统OpenWebUI集成LDAP用户权限认证(2)
为企业级AI交互系统OpenWebUI集成LDAP用户权限认证(2) 本文介绍如何OpenWebUI系统集成LDAP认证服务,及其用户权限及用户组设置。 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录…...
mac 被禁用docker ui后,如何使用lima虚拟机启动docker
本机macos 安装lima brew install lima创建配置 echo "\\ndynamic:\n big-sur:\n image: docker://docker:git\n linux:\n image: docker.io/limasoftware/ubuntu:20.04 \\n" > ~/.lima/default.yaml启动名叫default的虚拟机 limactl start default进…...
C#实现AES-CBC加密工具类(含完整源码及使用教程)
一、AES-CBC加密应用场景 AES(Advanced Encryption Standard)作为全球公认的安全加密标准,广泛使用在以下场景: API通信加密:保护HTTP接口传输的敏感数据(如身份令牌、支付信息)文件安全存储&…...
Unity辅助工具_头部与svn
Unity调用者按钮增加PlaySideButton using QQu; using UnityEditor; using UnityEngine; [InitializeOnLoad] public class PlaySideButton {static PlaySideButton(){UnityEditorToolbar.RightToolbarGUI.Add(OnRightToolbarGUI);UnityEditorToolbar.LeftToolbarGUI.Add(OnLe…...
VBA 数据库同一表的当前行与其他行的主键重复判断实现方案1
目的,判断是否主键重复,不重复则登录新数据,重复则不登录。 定义类型: DataRecord tableName 表名 rowNumber 行号 columnName 列名 data 数据 想要实现的代码逻辑如下: 模拟数据库的登录过程。假设…...
Pytorch系列教程:可视化Pytorch模型训练过程
深度学习和理解训练过程中的学习和进步机制对于优化性能、诊断欠拟合或过拟合等问题至关重要。将训练过程可视化的过程为学习的动态提供了有价值的见解,使我们能够做出合理的决策。训练进度必须可视化的两种方法是:使用Matplotlib和Tensor Board。在本文…...
CSS伸缩盒模型(弹性盒子)
伸缩盒模型(Flexbox,Flexible Box Layout)是 CSS 中一种一维布局模型,用于更高效地处理元素的对齐、分布和响应式布局。其核心思想是让容器内的子元素(称为“项目”)能够灵活地自动调整大小和位置以适应不同…...
C++蓝桥杯基础篇(十一)
片头 嗨~小伙伴们,大家好!今天我们来学习C蓝桥杯基础篇(十一),学习类,结构体,指针相关知识,准备好了吗?咱们开始咯~ 一、类与结构体 类的定义:在C中&#x…...
版本控制泄露源码 .svn
##相关知识 SVN源码泄露 SVN(subversion)是源代码版本管理软件,造成 SVN 源代码漏洞的主要原因是管理员操作不规范。“ 在使用 SVN 管理本地代码过程中,会自动生成一个名为 .svn 的隐藏文件夹,其中包含重要的源代码信…...
基于单片机的风速报警装置设计
标题:基于单片机的风速报警装置设计 内容:1.摘要 本设计聚焦于基于单片机的风速报警装置,旨在解决传统风速监测缺乏实时报警功能的问题。采用单片机作为核心控制单元,结合风速传感器采集风速数据。经实验测试,该装置能准确测量 0 - 60m/s 范…...
YOLOv12本地部署教程——42%速度提升,让高效目标检测触手可及
YOLOv12 是“你只看一次”(You Only Look Once, YOLO)系列的最新版本,于 2025 年 2 月发布。它引入了注意力机制,提升了检测精度,同时保持了高效的实时性能。在保持速度的同时,显著提升了检测精度。例如&am…...
Banana Pi OpenWRT One Wifi6 OpenWrt社区官方开源路由器评测
第一款不可破解、开源、版权软件、符合 FCC、CE 和 RoHS 的维修权路由器 OpenWRT项目今年已经20岁了,为了纪念这一时刻,Banana Pi OpenWrt One/AP-24.XY路由器开发系统已经上市。这是OpenWRT团队与硬件公司的第一个联合项目。选择 Banana Pi,…...
【算法】经典排序算法介绍+代码示例
排序算法介绍 1)冒泡排序 (Bubble Sort)2)选择排序(Selection Sort)3)插入排序(Insertion Sort)4)希尔排序(Shell Sort)5)归并排序(Me…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_02带边框和斑马纹的固定表头表格
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
【Linux】线程控制
目录 一、原生线程库: 二、线程控制: 1、线程创建: 2、线程等待: 自定义类型的接收对象: 编辑 3、线程终止: pthread_exit: pthread_cancel: 4、线程ID: 线程库的底层原…...
pyqt联合designer的运用和设置
PyQt Designer 简介 PyQt Designer 是一个用于创建和设计 PyQt 应用程序用户界面的可视化工具。它允许用户通过拖放方式添加和排列各种控件,如按钮、文本框、滑块等,并设置它们的属性和样式,从而快速构建出美观且功能完整的 UI 界面。 Windows版本:【免费】安装包别管啊啊…...
spring boot3.4.3+MybatisPlus3.5.5+swagger-ui2.7.0
使用 MyBatis-Plus 操作 books 表。我们将实现以下功能: 创建实体类 Book。 创建 Mapper 接口 BookMapper。 创建 Service 层 BookService 和 BookServiceImpl。 创建 Controller 层 BookController。 配置 MyBatis-Plus 和数据库连接。 1. 项目结构 src ├─…...
利用微软的 HTML 应用程序宿主程序的攻击
mshta.exe 是微软的 HTML 应用程序宿主程序(Microsoft HTML Application Host),属于 Windows 系统组件。它的核心功能是运行 .hta(HTML Application)文件,允许通过 HTML、JavaScript、VBScript 等技术创建交…...
【深度学习】读写文件
读写文件 到目前为止,我们讨论了如何处理数据,以及如何构建、训练和测试深度学习模型。 然而,有时我们希望保存训练的模型,以备将来在各种环境中使用(比如在部署中进行预测)。 此外,当运行一个…...
Bert的使用
一、Data.py # data负责产生两个dataloader from torch.utils.data import DataLoader, Dataset from sklearn.model_selection import train_test_split #给X,Y 和分割比例, 分割出来一个训练集和验证机的X, Y import torchdef read_file(path):data []label …...
Unity使用UGUI制作无限滑动列表
原理参照上一篇使用NGUI的制作无限滑动列表的文章 Unity 使用NGUI制作无限滑动列表_unity 滑动列表很多物体-CSDN博客 准备工作: 新建一个空物体命名为LoopList,并调整其大小, 并增加Scroll Rect组件(用于滑动)、Re…...
ThinkPHP6用户登录系统的全过程
ThinkPHP6用户登录系统的全过程涉及请求处理、数据传输、路由分发、控制器逻辑、模型验证及中间件协作等多个模块的交互。详细的过程解析如下: 1. 前端请求与路由分发 前端发起请求:用户在前端页面(如Vue组件或HTML表单)输入用户…...
C++全栈聊天项目(2) 单例模式封装Http管理者
完善注册类界面 先在注册类构造函数里添加lineEdit的模式为密码模式 ui->lineEdit_Passwd->setEchoMode(QLineEdit::Password); ui->lineEdit_Confirm->setEchoMode(QLineEdit::Password);我们在注册界面的ui里添加一个widget,widget内部包含一个tip居…...
【鸿蒙开发】OpenHarmony调测工具hdc使用教程(设备开发者)
00. 目录 文章目录 00. 目录01. OpenHarmony概述02. hdc简介03. hdc获取04. option相关的命令05. 查询设备列表的命令06. 服务进程相关命令07. 网络相关的命令08. 文件相关的命令09. 应用相关的命令10. 调试相关的命令11. 常见问题12. 附录 01. OpenHarmony概述 OpenHarmony是…...
ORACLE EBS数据库RELINK方式搭建克隆环境
ORACLE EBS系统的数据库,一般都安装了很多特定功能的小补丁来解决特定的BUG;因此对于已经安装好的系统,想要克隆一套测试环境、搭建一个新的备机做测试等,如果按照生产环境标准,则需要安装大量补丁,带来很大…...
MySQL regexp 命令
REGEXP命令是一种用于进行正则表达式匹配的运算符,允许在查询中使用正则表达式来匹配字符串模式1。 基本语法 基本的语法结构如下: SELECT * FROM table_name WHERE column_name REGEXP pattern; 这里,pattern是你要匹配的正则表达式模…...
前端实习到工作的经历
看了很多人的程序员生涯之路,我突然意识到我也该记录一些东西,因此有感而发。 我是一个24届毕业生,大三下就开始找前端实习,当时学校不让走,我们都是先面着然后准备放假就去。当时周围小伙伴都找好了,考完…...
Vue3——Fragment
文章目录 一、Fragment的核心意义1. 解决Vue2的单根限制问题2. 减少不必要的 DOM 嵌套3. 语义化和结构化 二、Fragment 的实现原理三、Fragment 使用方式1. 基本用法2. 结合条件渲染3. 动态组件 四、实际应用场景1. 列表/表格组件2. 布局组件3. 语义化标签 五、注意事项1. 属性…...
Linux_16进程地址空间
CPU内的寄存器只有一套,但是CPU内寄存器的数据可能会有多份! 一、程序地址空间 下面这个图对应的是内存吗?(实际上是虚拟的进程地址空间) 32位机器内存最大为多少? 32位操作系统的地址总线为32位&#x…...
职坐标机器学习编程实战:调试优化与自动化测试精要
内容概要 在机器学习编程实践中,代码调试优化与自动化测试工具的应用是构建高可靠性系统的核心环节。本书聚焦从数据预处理到模型部署的全流程,通过特征工程优化、训练过程监控及持续集成方案的设计,系统化解决算法工程化中的典型问题。在特…...
git文件过大导致gitea仓库镜像推送失败问题解决(push failed: context deadline exceeded)
问题描述: 今天发现gitea仓库推送到某个镜像仓库的操作几个月前已经报错终止推送了,报错如下: 首先翻译报错提示可知是因为git仓库大小超过1G限制。检查本地.git文件,发现.git文件大小已达到1.13G。确定是.git文件过大导致&…...
llvm数据流分析
llvm数据流分析 1.数据流分析2.LLVM实现2.1.常量传播2.2.活跃性分析 相关参考文档:DataFlowAnalysisIntro、ustc编译原理课程、南大程序分析课程1、南大程序分析课程2。 1.数据流分析 数据流分析在编译优化等程序分析任务上都有重要应用。通常数据流分析可被抽象为…...
Vite为什么选用Rollup打包?
Vite 在生产阶段使用 Rollup 打包,但这不是唯一选择。它的设计背后有明确的权衡和考量,同时开发者也可以选择其他替代方案。 一、为什么 Vite 默认使用 Rollup? 1. Rollup 的核心优势 • Tree-shaking:Rollup 的静态分析能力极强&…...
Docker 入门与实战指南
Docker 入门与实战指南 一、Docker 简介 Docker 是一个开源的容器化平台,允许开发者将应用程序及其依赖打包成一个可移植的容器。容器可以在任何安装了 Docker 的环境中运行,确保应用的一致性和可移植性。 1.1 为什么使用 Docker? 环境一…...
C# 常用数据类型
C# 数据类型分为 值类型、引用类型 和 特殊类型,以下是详细分类及对应范围/说明: 一、值类型(Value Types) 值类型直接存储数据,分配在栈内存中,默认不可为 null。 简单类型 整数类型…...
深入解读 JavaScript 中 `this` 的指向机制:覆盖所有场景与底层原理
this 是 JavaScript 中最容易引发困惑的核心概念之一,它的指向在不同场景下呈现截然不同的行为。本文将系统性地解析 this 的所有使用场景,结合代码示例和底层原理,帮助你彻底掌握其运行机制。 一、全局环境下的 this 1. 浏览器环境 在浏览器…...
无人机全景应用解析与技术演进趋势
无人机全景应用解析与技术演进趋势 ——从立体安防到万物互联的空中革命 一、现有应用场景全景解析 (一)公共安全领域 1. 立体安防体系 空中哨兵:搭载 77 GHz 77\text{GHz} 77GHz毫米波雷达(探测距离 5 km 5\text{km} 5km&…...
手写简易Tomcat核心实现:深入理解Servlet容器原理
目录 一、Tomcat概况 1. tomcat全局图 2.项目结构概览 二、实现步骤详解 2.1 基础工具包(com.qcby.util) 2.1.1 ResponseUtil:HTTP响应生成工具 2.1.2 SearchClassUtil:类扫描工具 2.1.3 WebServlet:自定义注解…...
【音视频】ffmpeg命令提取像素格式
1、提取YUV数据 提取yuv数据,并保持分辨率与原视频一致 使用-pix_fmt或-pixel_format指定yuv格式提取数据,并保持原来的分辨率 ffmpeg -i music.mp4 -t "01:00" -pixel_format yuv420p music.yuv提取成功后,可以使用ffplay指定y…...
深度剖析Redis:双写一致性问题及解决方案全景解析
在高并发场景下,缓存与数据库的双写一致性是每个开发者必须直面的核心挑战。本文通过5大解决方案,带你彻底攻克这一技术难关! 一、问题全景图:当缓存遇到数据库 1.1 典型问题场景 // 典型问题代码示例 public void updateProduc…...
Redis----大key、热key解决方案、脑裂问题
文章中相关知识点在往期已经更新过了,如果有友友不理解可翻看往期内容 出现脑裂问题怎么保证集群还是高可用的 什么是脑裂问题 脑裂说的就是当我们的主节点没有挂,但是因为网络延迟较大,然后和主节点相连的哨兵通信较差,之后主…...
Android 调用c++报错 exception of type std::bad_alloc: std::bad_alloc
一、报错信息 terminating with uncaught exception of type std::bad_alloc: std::bad_alloc 查了那部分报错c++代码 szGridSize因为文件太大,初始化溢出了 pEGM->pData = new float[szGridSize]; 解决办法 直接抛出异常,文件太大就失败吧 最后还增加一个日志输出,给…...
【从零开始学习计算机科学】操作系统(五)处理器调度
【从零开始学习计算机科学】操作系统(五)处理器调度 处理器调度一些简单的短程调度算法的思路先来先服务(First-Come-First-Served,FCFS)优先级调度及其变种最短作业优先调度算法(SJF)--非抢占式最短作业优先调度算法(SJF)--抢占式最高响应比优先调度算法轮转调度算法…...
LeetCode1871 跳跃游戏VII
LeetCode 跳跃游戏 IV:二进制字符串的跳跃问题 题目描述 给定一个下标从 0 开始的二进制字符串 s 和两个整数 minJump 和 maxJump。初始时,你位于下标 0 处(保证该位置为 0)。你需要判断是否能到达字符串的最后一个位置…...