23种设计模式-抽象工厂(Abstract Factory)设计模式
文章目录
- 一.什么是抽象工厂设计模式?
- 二.抽象工厂模式的特点
- 三.抽象工厂模式的结构
- 四.抽象工厂模式的优缺点
- 五.抽象工厂模式的 C++ 实现
- 六.抽象工厂模式的 Java 实现
- 七.代码解析
- 八.总结
类图: 抽象工厂设计模式类图
一.什么是抽象工厂设计模式?
抽象工厂模式(Abstract Factory Pattern) 是一种创建型设计模式,它提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。
与工厂方法模式的区别在于,抽象工厂模式更注重产品族的概念,可以同时创建多个相关的产品对象。
二.抽象工厂模式的特点
- 多产品创建:可以创建一组相关联的对象(如按钮和文本框)。
- 解耦性强:客户端只需调用工厂接口创建对象,而不需要关心具体实现。
- 可扩展性:可以通过增加新的工厂子类来扩展产品系列。
三.抽象工厂模式的结构
- AbstractFactory(抽象工厂):声明了一组创建产品的方法。
- ConcreteFactory(具体工厂):实现抽象工厂的接口,创建具体的产品。
- AbstractProduct(抽象产品):定义产品的接口。
- ConcreteProduct(具体产品):实现抽象产品接口的具体类。
- Client(客户端):通过工厂接口与具体产品交互。

四.抽象工厂模式的优缺点
- 优点:
- 易于扩展:增加新的产品族只需增加对应的具体工厂类和产品类。
- 封装性强:客户端与具体产品实现解耦。
- 符合开闭原则:通过扩展具体工厂类来支持新产品。
- 缺点:
- 增加复杂性:每增加一个产品族,都需要新增具体工厂和产品类。
- 不支持单一产品族扩展:如果只想增加单个产品,可能需要修改抽象工厂接口。
五.抽象工厂模式的 C++ 实现
#include <iostream>
#include <memory>
using namespace std;// 抽象产品A
class AbstractProductA {
public:virtual void MethodA() const = 0;virtual ~AbstractProductA() = default;
};// 抽象产品B
class AbstractProductB {
public:virtual void MethodB() const = 0;virtual ~AbstractProductB() = default;
};// 具体产品A1
class ConcreteProductA1 : public AbstractProductA {
public:void MethodA() const override {cout << "ConcreteProductA1::MethodA" << endl;}
};// 具体产品A2
class ConcreteProductA2 : public AbstractProductA {
public:void MethodA() const override {cout << "ConcreteProductA2::MethodA" << endl;}
};// 具体产品B1
class ConcreteProductB1 : public AbstractProductB {
public:void MethodB() const override {cout << "ConcreteProductB1::MethodB" << endl;}
};// 具体产品B2
class ConcreteProductB2 : public AbstractProductB {
public:void MethodB() const override {cout << "ConcreteProductB2::MethodB" << endl;}
};// 抽象工厂
class AbstractFactory {
public:virtual unique_ptr<AbstractProductA> CreateProductA() const = 0;virtual unique_ptr<AbstractProductB> CreateProductB() const = 0;virtual ~AbstractFactory() = default;
};// 具体工厂1
class ConcreteFactory1 : public AbstractFactory {
public:unique_ptr<AbstractProductA> CreateProductA() const override {return make_unique<ConcreteProductA1>();}unique_ptr<AbstractProductB> CreateProductB() const override {return make_unique<ConcreteProductB1>();}
};// 具体工厂2
class ConcreteFactory2 : public AbstractFactory {
public:unique_ptr<AbstractProductA> CreateProductA() const override {return make_unique<ConcreteProductA2>();}unique_ptr<AbstractProductB> CreateProductB() const override {return make_unique<ConcreteProductB2>();}
};// 客户端代码
void ClientCode(const AbstractFactory& factory) {auto productA = factory.CreateProductA();auto productB = factory.CreateProductB();productA->MethodA();productB->MethodB();
}int main() {cout << "Using ConcreteFactory1:" << endl;ConcreteFactory1 factory1;ClientCode(factory1);cout << "Using ConcreteFactory2:" << endl;ConcreteFactory2 factory2;ClientCode(factory2);return 0;
}
六.抽象工厂模式的 Java 实现
// 抽象产品A
interface ProductA {void methodA();
}// 抽象产品B
interface ProductB {void methodB();
}// 具体产品A1
class ConcreteProductA1 implements ProductA {public void methodA() {System.out.println("ConcreteProductA1::methodA");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {public void methodA() {System.out.println("ConcreteProductA2::methodA");}
}// 具体产品B1
class ConcreteProductB1 implements ProductB {public void methodB() {System.out.println("ConcreteProductB1::methodB");}
}// 具体产品B2
class ConcreteProductB2 implements ProductB {public void methodB() {System.out.println("ConcreteProductB2::methodB");}
}// 抽象工厂
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA1();}public ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA2();}public ProductB createProductB() {return new ConcreteProductB2();}
}// 客户端代码
public class AbstractFactoryDemo {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();productA1.methodA();productB1.methodB();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.methodA();productB2.methodB();}
}
七.代码解析
- 抽象产品类:
- AbstractProductA 和 AbstractProductB 是抽象类,定义了各自的接口方法(如 MethodA 和 MethodB)。
- 具体产品类:
- ConcreteProductA1 和 ConcreteProductA2 实现了 AbstractProductA 接口,表示同一产品族中的不同产品。
- ConcreteProductB1 和 ConcreteProductB2 实现了 AbstractProductB 接口。
- 抽象工厂类:
- AbstractFactory 提供了创建产品的方法接口(CreateProductA 和 CreateProductB),由具体工厂实现。
- 具体工厂类:
- ConcreteFactory1 创建产品族 ConcreteProductA1 和 ConcreteProductB1。
- ConcreteFactory2 创建产品族 ConcreteProductA2 和 ConcreteProductB2。
- 客户端代码:
- 客户端通过抽象工厂创建产品,不需要知道具体工厂和产品的实现细节。
- 多态使得客户端代码具有很强的灵活性。
八.总结
抽象工厂模式在需要创建一组相关对象时非常有用,同时也很好地遵循了依赖倒置原则和开闭原则。通过抽象工厂,客户端只需关心工厂接口,而不需要了解具体产品的实现,从而实现了代码的解耦。尽管增加了系统的复杂性,但在复杂系统中,它可以显著提高代码的灵活性和可维护性。
应用场景:
- 需要创建一组相关或相互依赖的对象:如操作系统中的窗口、按钮和文本框。
- 产品族的概念明确:如不同品牌的家电(冰箱和电视)。
- 客户端不需要知道产品的具体实现:如通过配置文件动态加载具体工厂类。
相关文章:
23种设计模式-抽象工厂(Abstract Factory)设计模式
文章目录 一.什么是抽象工厂设计模式?二.抽象工厂模式的特点三.抽象工厂模式的结构四.抽象工厂模式的优缺点五.抽象工厂模式的 C 实现六.抽象工厂模式的 Java 实现七.代码解析八.总结 类图: 抽象工厂设计模式类图 一.什么是抽象工厂设计模式?…...
手机上怎么拍证件照,操作简单且尺寸颜色标准的方法
在数字化时代,手机已成为我们日常生活中不可或缺的一部分。它不仅是通讯工具,更是我们拍摄证件照的便捷利器。然而,目前证件照制作工具鱼龙混杂,很多打着免费名号的拍照软件背后却存在着泄漏用户信息、照片制作不规范导致无法使用…...
IDEA报错: java: JPS incremental annotation processing is disabled 解决
起因 换了个电脑打开了之前某个老项目IDEA启动springcloud其中某个服务直接报错,信息如下 java: JPS incremental annotation processing is disabled. Compilation results on partial recompilation may be inaccurate. Use build process “jps.track.ap.depen…...
OCR实现微信截图改名
pip install paddlepaddle -i https://pypi.tuna.tsinghua.edu.cn/simple/ ──(Sat,Nov30)─┘ pip install shapely -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install paddleo…...
第一届“吾杯”网络安全技能大赛 Writeup
战队信息 战队名称:在你眼中我是誰,你想我代替誰? 战队排名:13 Misc Sign Hex 转 Str,即可得到flag。 原神启动! 不好评价,stegsolve 秒了: WuCup{7c16e21c-31c2-439e-a814-b…...
再谈Java中的String类型是否相同的判断方法
目录 第一部分 代码展示 画图展示 第二部分 代码展示 画图展示 第一部分 代码展示 画图展示 第二部分 代码展示 画图展示...
<一>51单片机环境
目录 1,51单片机开发语言是C,环境keil 1.1,工程创建 1.2用什么把代码放进单片机里面 2,初识代码 1,51单片机开发语言是C,环境keil 1.1,工程创建 1. 创建项目工程文件夹,可以当作模板Template 2. 创建文件,取名main.c 3,编译,选择输出文…...
【0x0001】HCI_Set_Event_Mask详解
目录 一、命令概述 二、命令格式 三、命令参数说明 四、返回参数说明 五、命令执行流程 5.1. 主机准备阶段 5.2. 命令发送阶段 5.3. 控制器接收与处理阶段 5.4. 事件过滤与反馈阶段 5.5. 主机处理(主机端) 5.6. 示例代码 六、命令应用场景 …...
第三方Express 路由和路由中间件
文章目录 1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。2、Express路由1.路由方法2.路由路径3.路由处理程序 3. 模块化路由4. Express中间件1.中间件简介2.中间件分类3.自定义中间件 1、Express 应用使用回调函数的参数&am…...
七、Python —— 元组、集合和字典
文章目录 一、元组1.1、元组的初始化1.2、元组的解包1.3、元组的比较运算1.4、元组的其他操作 二、集合 set2.1、集合的初始化2.2、集合的常用操作2.3、使用 for 循环遍历集合 三、字典 map3.1、字典的初始化3.2、字典的常用操作3.3、使用 for 循环遍历字典 四、补充 一、元组 …...
Aes加解密
加解密概念 加密AES加密填充模式加密模式示例 加密 通过一系列计算将明文转换成一个密文。 加密和解密的对象通常是字节数组(有的语言动态数组类比切片) 加密后的数据,可能有很多是不可读字符。通常会将其转换为可见的字符串。 直接将字节…...
【时时三省】Tessy 故障入侵 使用教程
目录 1,故障入侵 介绍 故障入侵适用场景: 打故障入侵的方法和选项介绍: 2,打单个函数的故障入侵 3,打整体用例的故障入侵 4,一个函数打多个故障入侵 山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,故障入侵 介绍 故障入侵适用场景: 故障入侵 …...
.NET 9 AOT的突破 - 支持老旧Win7与XP环境
引言 随着技术的不断进步,微软的.NET 框架在每次迭代中都带来了令人惊喜的新特性。在.NET 9 版本中,一个特别引人注目的亮点是 AOT( Ahead-of-Time)支持,它允许开发人员将应用程序在编译阶段就优化为能够在老旧的 Win…...
CondaValueError: Malformed version string ‘~‘: invalid character(s).
问题描述:在window下使用conda安装任何包都会报错。报错信息是CondaValueError: Malformed version string ~: invalid character(s). 解决办法:把.condarc文件的源地址删除(八成是源地址访问不了了),只保存默认的&am…...
01-Ubuntu24.04LTS上安装PGSQL
目录 一、准备工作 1.1、系统要求 1.2 、更新 Ubuntu 系统 1.3 、安装依赖 1.4 、添加 PostgreSQL 16 软件源 二、安装 PostgreSQL 16 数据库 三、管理 PostgreSQL 服务 四、PostgreSQL 管理操作 4.1 、访问 Postgres 超级用户账户 4.2 、创建数据库并设置管理权限 4…...
Esp32使用micropython基于espnow实现语音对讲机
ESP-NOW协议介绍 ESP-NOW 是乐鑫自主研发的无连接通信协议,具有短数据包传输功能。该协议使多个设备能够以简单的方式相互通信。ESP-NOW 支持以下功能: 加密和未加密的单播通信; 混合加密和未加密的对等设备; 最多可携带 250 字节 的有效载荷; 发送回调功能,可以设置用于…...
Docker 容器隔离关键技术:SELinux
Docker 容器隔离关键技术:SELinux SELinux(Security-Enhanced Linux) 是 Linux 内核中的一项安全机制,用于实现强制访问控制(MAC)。Docker 利用了 SELinux 来增强容器的隔离性,通过对文件、进程…...
Java并发07之ThreadLocal
文章目录 1 ThreadLocal原理2 内部结构3 内存泄露问题4 entry的key为什么被设计为弱引用 1 ThreadLocal原理 ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问时能保证各个线程的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private st…...
【单细胞数据库】癌症单细胞数据库CancerSEA
数据库地址:home (hrbmu.edu.cn) Cite Huating Yuan, Min Yan, Guanxiong Zhang, Wei Liu, Chunyu Deng, Gaoming Liao, Liwen Xu, Tao Luo, Haoteng Yan, Zhilin Long, Aiai Shi, Tingting Zhao, Yun Xiao, Xia Li, CancerSEA: a cancer single-cell state atlas…...
Rsa加解密 + 签名验签
Rsa加解密 概述聚合算法名称(用于创建加密器)基本概念填充方式分块加密 基本使用生成密钥加解密创建加密器设置模式(加密)、公钥对明文加密,并对结果进行Base64编码对以上结果,进行解密 设置模式࿰…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
