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编码对以上结果,进行解密 设置模式࿰…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
用鸿蒙HarmonyOS5实现中国象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...