C++ 设计模式——抽象工厂模式
抽象工厂模式
抽象工厂模式
- 抽象工厂模式
- 主要组成部分
- 代码实现
- 抽象工厂模式模式的 UML 图
- 抽象工厂模式 UML 图解析
- 优点和缺点
- 适用场景
抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。它通常用于需要创建多个产品族的场景。
引入“抽象工厂模式”设计模式的定义(实现意图):提供一个接口,让该接口负责创建一系列相关或者相互依赖的对象,而无须指定它们具体的类。
主要组成部分
- 抽象工厂(AbstractFactory):定义创建抽象产品的接口。它声明了用于创建不同类型产品的方法。
- 具体工厂(ConcreteFactory):实现抽象工厂接口,创建具体产品。每个具体工厂负责生成一组相关的具体产品。
- 抽象产品(AbstractProduct):定义产品的接口。它为具体产品提供了一个公共的接口。
- 具体产品(ConcreteProduct):实现抽象产品接口的具体类。每个具体产品对应于一个具体工厂。
代码实现
以下是使用抽象工厂模式创建不同类型的怪物对象的代码示例:
#include <iostream>
#include <string>using namespace std;// 怪物父类
class Monster {
public:Monster(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}virtual ~Monster() {} // 虚析构函数protected:int m_life; // 生命值int m_magic; // 魔法值int m_attack; // 攻击力
};// 沼泽亡灵类怪物
class M_Undead_Swamp : public Monster {
public:M_Undead_Swamp(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个沼泽的亡灵类怪物来到了这个世界" << endl;}
};// 沼泽元素类怪物
class M_Element_Swamp : public Monster {
public:M_Element_Swamp(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个沼泽的元素类怪物来到了这个世界" << endl;}
};// 沼泽机械类怪物
class M_Mechanic_Swamp : public Monster {
public:M_Mechanic_Swamp(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个沼泽的机械类怪物来到了这个世界" << endl;}
};// 山脉亡灵类怪物
class M_Undead_Mountain : public Monster {
public:M_Undead_Mountain(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个山脉的亡灵类怪物来到了这个世界" << endl;}
};// 山脉元素类怪物
class M_Element_Mountain : public Monster {
public:M_Element_Mountain(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个山脉的元素类怪物来到了这个世界" << endl;}
};// 山脉机械类怪物
class M_Mechanic_Mountain : public Monster {
public:M_Mechanic_Mountain(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个山脉的机械类怪物来到了这个世界" << endl;}
};// 城镇亡灵类怪物
class M_Undead_Town : public Monster {
public:M_Undead_Town(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个城镇的亡灵类怪物来到了这个世界" << endl;}
};// 城镇元素类怪物
class M_Element_Town : public Monster {
public:M_Element_Town(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个城镇的元素类怪物来到了这个世界" << endl;}
};// 城镇机械类怪物
class M_Mechanic_Town : public Monster {
public:M_Mechanic_Town(int life, int magic, int attack) : Monster(life, magic, attack) {cout << "一个城镇的机械类怪物来到了这个世界" << endl;}
};// 所有工厂类的父类
class M_ParFactory {
public:virtual Monster* createMonster_Undead() = 0; // 创建亡灵类怪物virtual Monster* createMonster_Element() = 0; // 创建元素类怪物virtual Monster* createMonster_Mechanic() = 0; // 创建机械类怪物virtual ~M_ParFactory() {} // 虚析构函数
};// 沼泽地区的工厂
class M_Factory_Swamp : public M_ParFactory {
public:virtual Monster* createMonster_Undead() override {return new M_Undead_Swamp(300, 50, 120); // 创建沼泽亡灵类怪物}virtual Monster* createMonster_Element() override {return new M_Element_Swamp(200, 80, 110); // 创建沼泽元素类怪物}virtual Monster* createMonster_Mechanic() override {return new M_Mechanic_Swamp(400, 0, 90); // 创建沼泽机械类怪物}
};// 山脉地区的工厂
class M_Factory_Mountain : public M_ParFactory {
public:virtual Monster* createMonster_Undead() override {return new M_Undead_Mountain(300, 50, 80); // 创建山脉亡灵类怪物}virtual Monster* createMonster_Element() override {return new M_Element_Mountain(200, 80, 100); // 创建山脉元素类怪物}virtual Monster* createMonster_Mechanic() override {return new M_Mechanic_Mountain(600, 0, 110); // 创建山脉机械类怪物}
};// 城镇的工厂
class M_Factory_Town : public M_ParFactory {
public:virtual Monster* createMonster_Undead() override {return new M_Undead_Town(300, 50, 80); // 创建城镇亡灵类怪物}virtual Monster* createMonster_Element() override {return new M_Element_Town(200, 80, 100); // 创建城镇元素类怪物}virtual Monster* createMonster_Mechanic() override {return new M_Mechanic_Town(400, 0, 110); // 创建城镇机械类怪物}
};// 使用示例
int main() {M_ParFactory* factory = new M_Factory_Swamp();Monster* undead = factory->createMonster_Undead();Monster* element = factory->createMonster_Element();Monster* mechanic = factory->createMonster_Mechanic();// 释放内存delete undead;delete element;delete mechanic;delete factory;return 0;
}
抽象工厂模式模式的 UML 图

抽象工厂模式 UML 图解析
- 类与类之间的关系:
Monster类是所有具体怪物类的父类,子类(如M_Undead_Swamp、M_Element_Swamp、M_Mechanic_Swamp等)通过实线箭头与父类连接,箭头指向Monster类,表示继承关系。M_ParFactory是抽象工厂类,定义了创建不同类型怪物的接口。具体工厂类(如M_Factory_Swamp、M_Factory_Mountain、M_Factory_Town)通过实线箭头与M_ParFactory类连接,表示继承关系。
- 依赖关系:
- 具体工厂类(如
M_Factory_Swamp等)与具体怪物类(如M_Undead_Swamp等)之间存在虚线箭头,表示依赖关系。具体工厂类负责实例化具体怪物类的对象,箭头指向被实例化的类。
- 具体工厂类(如
- 稳定与变化部分:
- 稳定部分:
Monster类和M_ParFactory类是稳定部分,不需要频繁修改。 - 变化部分:具体怪物类(如
M_Undead_Swamp、M_Element_Swamp等)和具体工厂类(如M_Factory_Swamp等)属于变化部分。当需要添加新类型的怪物时,只需增加新的具体工厂类和具体怪物类,而不需要修改稳定部分。
- 稳定部分:
- 扩展性:
- 当需要引入新类型的怪物(如
M_Beast),只需创建一个新的具体工厂类(如M_Factory_Beast)和对应的怪物类(如M_Beast),而不需要更改现有的工厂接口。这符合开闭原则:对扩展开放,对修改关闭。
- 当需要引入新类型的怪物(如
- 隐藏实现细节:
- 如果
M_ParFactory类及其具体实现由第三方开发,开发者只需通过抽象工厂接口与工厂交互,而无需了解具体的怪物类(如M_Undead_Swamp等),实现了对具体实现的隐藏。
- 如果
- 接口扩展:
M_ParFactory中的接口可以根据需要进行扩展,例如新增创建其他类型对象的方法(如 NPC),使得工厂能够支持更丰富的对象创建。
优点和缺点
优点:
- 解耦合:客户端代码与具体产品的实现解耦,便于维护和扩展。修改产品的实现不会影响到客户端。
- 一致性:可以确保一组产品的一致性,避免在创建产品时出现不匹配的情况。例如,创建一个特定类型的怪物时,工厂会确保所有相关的属性和行为都符合预期。
- 易于扩展:新增产品类型时,只需扩展工厂类和相应的产品类,而无需修改现有代码,符合开闭原则。
- 隔离变化:将产品的创建逻辑集中在工厂中,减少了产品类之间的依赖,便于管理和控制变化。
缺点:
- 系统复杂性增加:引入抽象工厂模式会增加系统的复杂性,特别是在产品种类较多时,工厂类和产品类的数量也会增加。
- 维护成本:随着产品族的增加,维护抽象工厂及其子类的成本可能会提升,特别是当需要对多个工厂进行修改时。
- 难以支持新产品:如果需要支持新类型的产品,可能需要修改现有的工厂接口和实现,这可能导致较大的代码变动。
- 运行时开销:由于使用了多层抽象,可能会引入一定的运行时开销,尤其是在频繁创建对象的场景中。
适用场景
- 产品族的创建:当系统需要创建一组相关或相互依赖的产品时,使用抽象工厂模式可以确保产品的一致性和完整性。
- 需要解耦的系统:当需要将产品的创建与使用分离,减少系统之间的耦合度时,抽象工厂模式是一个理想的选择。
- 需要支持多个产品变体:在需要支持不同变体的情况下,例如不同地区的怪物、不同类型的用户界面组件等,抽象工厂模式可以有效管理这些变体。
- 需要扩展产品类型:当系统需要频繁扩展新产品类型时,抽象工厂模式提供了良好的扩展机制,符合开闭原则。
- 框架设计:在设计框架或库时,抽象工厂模式可以为用户提供灵活的产品创建接口,用户可以根据需要实现具体的工厂类。
相关文章:
C++ 设计模式——抽象工厂模式
抽象工厂模式 抽象工厂模式 抽象工厂模式主要组成部分代码实现抽象工厂模式模式的 UML 图抽象工厂模式 UML 图解析优点和缺点适用场景 抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。它通常用于需要创建多个产品…...
《亿级流量系统架构设计与实战》第十一章 Timeline Feed服务
Timeline Feed服务 一、概述1、分类2、功能 二、设计原理1、拉模式与用户发件箱2、推模式与用户收件箱3、推拉模式结合 三、关键技术1、内容与用户收件箱的交互(推模式)2、推送拆分子任务3、收件箱模型设计 内容总结自《亿级流量系统架构设计与实战》 一…...
氙灯老化试验箱试验机
氙灯老化试验箱,采用6.5KW大功率的精密水冷式氙灯,曝晒面积达到了6500cm2 功能强大,测试结果可靠 ◆ 满足国内外所有氙灯测试标准要求。 ◆ 采用氙灯灯管及滤光器组件,保证试验数据的可比性和重现性。 ◆ 自动旋转式三层鼓型样板架…...
【Qt】常用控件QRadioButton
常用控件QRadioButton QRadioButton是单选按钮,可以在多个选项中选择一个。 作为QAbstractButton和QWidget的子类,其属性和用法,对于QRadioButton同样适用。 属性说明 checkable 是否能选中 checked 是否已经被选中. checkable 是 checked…...
Mysql 离线版下载安装-(详细版)
Mysql 离线版下载安装-(详细版) 文章目录 Mysql 离线版下载安装-(详细版)1.0 下载地址2.0 解压到本地2.0.1 配置环境变量2.0.2 新建mysql配置文件ini2.0.3使用管理员启动 cmd 3.0 初始化密码忘记了4.0 修改初始化密码5.0 使用可视化工具登录Mysql 1.0 下载地址 地址࿱…...
Spring Boot和OCR构建车牌识别系统
博客主页: 南来_北往 系列专栏:Spring Boot实战 OCR介绍 OCR(Optical Character Recognition)是光学字符识别技术的缩写,它能够将图像中的文本转换为机器可读和编辑的数字文本格式。这种技术广泛应用于数据输入、文档管理…...
Java-自定义注解中成员变量是Class<?>
在Java中,自定义注解可以包含各种类型的成员变量,包括 Class<?> 类型。这种类型的成员变量 通常用于表示某个类的类型信息。下面我将详细介绍如何定义一个包含 Class<?> 类型成员变量的 自定义注解,并给出一些示例代码。 1. 定义自定义注解 定义一个自定义…...
SX_UNIX套接字通信_15
UNIX套接字通信的优势: UNIX套接字通信常用于一个项目中的进程之间通信,UNIX提供了与网络套接字相似的特性,但是避免了网络延迟,提高了性能,但是它只能在同一台机器上使用,无法跨越网络的进程间通信 实例&…...
JS模块化总结 | CommonJS、ES6
BV13W42197jR 个人笔记 目录 JS模块化基础知识1. 概述1.1 什么是模块化1.2 为什么需要模块化? 2 模块化规范3 导入&导出4 CommonJS规范4.1 初步体验4.2 导出数据4.3 导入数据4.4 扩展理解4.5 浏览器端运行 5 ES6模块化规范5.1 初步体验5.2 Node中运行ES65.3 导出数据①分别…...
25考研计算机组成原理复习·3.5高速缓冲存储器
高速缓冲存储器Cache 工作原理:将某些主存块复制到Cache中,缓和CPU与主存之间的速度矛盾局部性原理 时间局部性:现在访问的地址,不久之后也很可能被再次访问空间局部性:现在访问的地址,其附近的地址也很可…...
餐厅管理系统
目录 一、 系统简介 1.1需求分析 1.2 编程环境与工具 二、 系统总体设计 2.1 系统的功能模块图。 2.2 各功能模块简介。 三、 主要业务流程 (1)用户及管理员登录流程图 (2)信息添加流程 (3…...
杭州百腾教育科技 TiDB 6.5 to 7.5 升级记录
作者: reAsOn2010 原文来源: https://tidb.net/blog/612103f3 背景 使用 TiDB 作为我们的全量数据库已经有六七年了,当时还是 2.0 版本。早期TiDB的迭代和新特性的发布对于实际使用的影响还是很大的,所以从那个时候开始就有每…...
Redis的缓存穿透、击穿、雪崩
目录 缓存穿透 定义: 解决方法: 缓存击穿 定义: 解决方案: 缓存雪崩 定义: 解决方案: 缓存穿透、缓存击穿和缓存雪崩的区别 缓存穿透 定义: 查询一个不存在的数据,数据库未…...
【Django开发】前后端分离django美多商城项目第1篇:欢迎来到美多 项目主要页面介绍【附代码文档】
本教程的知识点为: 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后…...
【软件造价咨询】信息化项目预算评审看什么?
在信息化项目预算评审中,各方往往只重视预算金额部分,而忽视了项目建设的全局性和整体性把关,导致信息系统的重复建设、分散建设、业务和系统两张皮、重功能轻数据、重投资轻方案等问题频出,从而大幅降低财政投资效益。 例如&…...
第37讲:Cephfs文件系统的正确使用姿势
文章目录 1.Cephfs文件系统简介2.Cephfs文件系统细节介绍2.1.Cephfs文件系统多客户端隔离挂载2.2.Ceph集群中多个Cephfs如何单独使用 3.挂载多个Cephfs文件系统4.Cephfs文件系统多客户端隔离挂载实战4.1.创建一个Cephfs文件系统4.2.将Cephfs文件系统挂载到本地路径4.3.在Cephfs…...
单片机烧录
在设计芯片的时候,关于烧录的环节是一个不得不考虑的问题。 我们首先排除掉,由外部直接硬件操控FLASH 的方案,这个方案有很多缺点。 1、每个IC使用的FLASH型号是各不相同的,每种型号的FLASH的烧录命令和流程都有差别,这…...
mysql实现分布式锁
利用数据库的悲观锁实现分布式锁,实际应用中要考虑mysql的高可用。 DistributedLock.h #ifndef DistributedLock_H_ #define DistributedLock_H_// // DistributedLock.h: // #include "base/MySQLDriver.h" class CDistributedLock { public://// Construction/D…...
MySQL快速使用
关系型数据库(RDBMS):建立在关系模型基础上,由多张相互连接的二维表组成的数据库 特点:使用表存储数据,格式统一方便维护;使用SQL语言操作,标准统一使用方便 通用语法: …...
LeetCode41.缺失的第一个正数
1. 题目大意 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 2. 思路分析 示例 1: 输入:nums [3,4,-1,1] 输出:2 解释࿱…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
