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 解释࿱…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...