当前位置: 首页 > news >正文

设计模式之抽象工厂模式

前言

工厂模式一般指的是简单工厂模式、工厂方法模式、抽象工厂模式,这是三种工厂模式的最后一篇,其他两种的文章链接如下:

设计模式之简单工厂模式-CSDN博客

设计模式之工厂方法模式-CSDN博客

建议三种模式放在一起对比学习,更能领会其中的奥秘。看懂UML类图,更是奥秘中的奥秘哦,在UML类图中不同的箭头和线条,代表的意义是不同的,发现有很多人都画错了,这里简单的梳理了一下,如果需要可以移步这里:设计模式之基础:UML类图怎么看?_uml图怎么看-CSDN博客

什么是抽象工厂模式?

抽象工厂模式是一种创建型的工厂模式,它提供了一个接口,使客户端可以在不指定具体产品的情况下创建多个产品组中的产品对象。当存在多个抽象角色时,抽象工厂模式可以用来创建一个工厂,该工厂能够根据需要生成相应类型的产品。这种模式将产品的生成和使用解耦,使得客户端无需了解具体产品的实现细节。

抽象工厂模式的核心思想是将工厂封装成了一个抽象接口,通过这个接口来创建产品。它允许客户端通过调用抽象工厂的接口来生成多个产品族中的产品对象,而无需知道每个产品族的实现细节。抽象工厂模式适用于存在多个产品族的情况,这些产品族具有不同的实现,但是客户端需要使用多个产品族中的产品。通过使用抽象工厂模式,客户端可以灵活地使用不同的产品族,而无需对代码进行大量修改。

与工厂方法模式有什么区别?

抽象工厂模式和工厂方法模式都是设计模式中的对象创建型模式,主要用于封装对象的创建过程,以减少代码耦合。两种模式之间存在以下区别:

  1. 工厂角色不同:在工厂方法模式中,工厂方法是实现客户端与具体产品类解耦的关键,客户端通过继承或实现工厂方法实现创建产品的功能。而在抽象工厂模式中,抽象工厂是客户端与具体产品类解耦的关键,客户端通过实例化抽象工厂对象并调用其创建产品的方法实现创建产品的功能。
  2. 创建产品的模式不同:工厂方法模式中,每个具体工厂类只能创建一个具体产品类的实例,即“一对一”的关系。而在抽象工厂模式中,每个具体工厂类可以创建多个具体产品类的实例,即“一对多”的关系。
  3. 产品类型不同:在工厂方法模式中,工厂方法返回的产品类型是固定的,即每个具体工厂类只能创建一个固定类型的产品。而在抽象工厂模式中,抽象工厂返回的产品类型可以是多种多样的,即每个具体工厂类可以创建多个不同类型的产品。

总之,抽象工厂模式相对于工厂方法模式,更适用于创建一系列相关或相互依赖的对象,以及对产品进行分类和组织的情况。

抽象工厂UML类图

在抽象工厂模式中,存在四种角色:

  1. 抽象工厂角色(Abstract Factory):担任这个角色的是工厂方法模式的核心,它是与应用系统业务逻辑无关的。抽象工厂包含对多个产品结构的声明,任何工厂类都必须实现这个接口。
  2. 具体工厂角色(Concrete Factory):这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的业务逻辑紧密相关的。具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。
  3. 抽象产品角色(Abstract Product):担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  4. 具体产品角色(Concrete Product):抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。

抽象工厂实现示例

还以女娲造人的传说举一个例子:刚开始造人,女娲觉得还挺有意思的,造的时间长了,都是黄皮肤的中国人,显得很单调,没啥意思了,于是拓展了一下业务,开始造黑色皮肤的非洲人了,用抽象工厂模式来演示这个过程会是什么样呢?

UML类图如下:

伪代码示例如下:

public interface Human {/*** 人类会吃东西*/void eat();/*** 人类会喝东西*/void drink();
}
public class YellowMan implements Human {@Overridepublic void eat() {System.out.println("黄色皮肤的中国男人在吃东西");}@Overridepublic void drink() {System.out.println("黄色皮肤的中国男人在喝水");}
}
public class YelloWoman implements Human {@Overridepublic void eat() {System.out.println("黄色皮肤的中国女人在吃东西");}@Overridepublic void drink() {System.out.println("黄色皮肤的中国女人在喝水");}
}
public interface HumanFactory {Human createMan();Human createWoman();
}
public class YelloHumanFactory implements HumanFactory{@Overridepublic Human createMan() {return new YellowMan();}@Overridepublic Human createWoman() {return new YelloWoman();}
}
public class BlackHumanFactory implements HumanFactory{@Overridepublic Human createMan() {return new BlackMan();}@Overridepublic Human createWoman() {return new BlackWoman();}
}
public class Test {public static void main(String[] args) {HumanFactory yellowHumanFactory=new YelloHumanFactory();Human man = yellowHumanFactory.createMan();Human woman = yellowHumanFactory.createWoman();man.eat();man.drink();woman.eat();woman.drink();HumanFactory blackHumanFactory=new BlackHumanFactory();Human man1 = blackHumanFactory.createMan();Human woman1 = blackHumanFactory.createWoman();man1.eat();man1.drink();woman1.eat();woman1.drink();}
}

女娲这都造人业务都拓展到海外了,光能造黄种人、黑种人怎么行,还想造白种人怎么办呢?很简单:

1、实现Human接口,再实现一个白种男人、一个白种女人的类;

2、实现HumanFactory接口,再实现一个白种人的制造工厂;

public class WhiteMan implements Human {@Overridepublic void eat() {System.out.println("白种欧洲男人吃东西");}@Overridepublic void drink() {System.out.println("白种欧洲男人在喝水");}
}
public class WhiteWoman implements Human {@Overridepublic void eat() {System.out.println("白种欧洲女人在吃东西");}@Overridepublic void drink() {System.out.println("白种欧洲女人在喝水");}
}
public class WhiteHumanFactory implements HumanFactory{@Overridepublic Human createMan() {return new WhiteMan();}@Overridepublic Human createWoman() {return new WhiteWoman();}
}
public class Test {public static void main(String[] args) {HumanFactory whiteHumanFactory=new WhiteHumanFactory();Human man2 = whiteHumanFactory.createMan();Human woman2 = whiteHumanFactory.createWoman();man2.eat();man2.drink();woman2.eat();woman2.drink();}
}

有一天女娲觉得光造些男人、女人太单调了,男人、女人之间老是干架,怎么调合一下呢?那就造一些可爱小朋友吧。这时就会发现,如果还使用抽象工厂模式,就会很尴尬:HumanFactory接口里只有造男人、造女人的抽象方法,如果再加一个造小朋友的接口,就要对HuanFactory接口及其实现类具体工厂修改,这就破坏了开闭原则。如果除了造黑人、白人、黄人外,还想造点绿巨人,其实倒还好,和增加造白人的逻辑一样。这就是在决定是否使用抽象工厂模式的秘密所在,如果要扩展的是一个产品族,比较简单且适用,如果想丰富某一产品族的某个产品系列,就比较麻烦了;

抽象工厂应用场景

有没有发现这种方式非常好?完全符合开闭原则,无须对原有系统进行修改;下面就总结一下抽象工厂模式的实际应用场景有哪些?

  1. 产品组装:在现实生活中,抽象工厂模式最典型的例子就是产品的组装。例如,在电脑的组装过程中,我们通常需要选择一系列的配件,如CPU、硬盘、内存、主板、电源、机箱等。选择不同的配件,组装出来的电脑是不同的,这就可以看作是在使用不同的工厂来生产不同的产品。
  2. 提供产品类库:如果我们需要提供一个产品类库,但只想显示它们的接口而不是实现,那么就可以使用抽象工厂模式。例如,在设计一个绘图软件时,我们可能希望提供一个图形类库,但并不想暴露出每个图形的具体实现细节,这时就可以使用抽象工厂模式来生成各种图形对象。
  3. 多产品系列:如果一个系统需要由多个产品系列中的一个来配置,那么也可以使用抽象工厂模式。例如,在汽车制造中,可能需要根据用户的选择来配置不同的汽车模型。
  4. 独立于产品的创建、组合和表示:如果一个系统需要独立于它的产品的创建、组合和表示,那么也可以使用抽象工厂模式。例如,在开发一个游戏引擎时,我们可能希望游戏开发者能够使用我们提供的引擎来创建各种类型的游戏,而无需关心游戏引擎底层的具体实现。

总结

抽象工厂模式是一种设计程序时的工程方法,前面也说过,方法是为了解决问题的,不是灵丹妙药,用上了就一定很好,是绝不能生搬硬套的,重在理解和灵活运用。

对于抽象工厂模式有以下优点:

  1. 隔离了具体类的生成,使得客户端并不需要知道什么被创建。
  2. 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
  3. 增加新的产品族很方便,无须修改已有系统,符合开闭原则。

抽象工厂模式也有一些缺点:

  1. 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,违背了开闭原则。
  2. 如果客户端需要创建多个产品族的多个对象,那么代码会变得很冗长和复杂。
  3. 如果产品族之间有依赖关系,那么需要仔细考虑如何处理这些依赖关系,以避免出现循环依赖或其他问题。

因此,在使用抽象工厂模式时,需要根据具体的情况来考虑其优缺点,并决定是否使用该模式。

相关文章:

设计模式之抽象工厂模式

前言 工厂模式一般指的是简单工厂模式、工厂方法模式、抽象工厂模式,这是三种工厂模式的最后一篇,其他两种的文章链接如下: 设计模式之简单工厂模式-CSDN博客 设计模式之工厂方法模式-CSDN博客 建议三种模式放在一起对比学习,…...

Compose预处理组件大比拼:性能、应用场景和可视化对比总结

在机器学习的世界里,预处理组件就像是厨师的烹饪工具。选择合适的工具不仅可以让整个烹饪过程更加顺畅,还能确保最终的菜肴更加美味。 本文将深入探讨四种“烹饪工具”:TransformedTargetRegressor、make_column_transformer、make_column_selector和ColumnTransformer。通…...

【小米】Linux 实习生

下午不准备去图书馆自习来着,中午就狠狠地多睡了一个小时,三点起床靠在椅子上剥柚子,太爽了,这秋天的下午。“邮件:小米公司邀请你预约面试时间”.......... 我擦,投了一个月了,认真准备的时候…...

python一点通:coroutine (协程)是什么和重要知识点?

协程已经成为Python用于编写并发和异步代码的重要工具之一。在这篇博客文章中,我们将深入探讨协程是什么,它们的优点,以及它们与传统的线程和进程有何不同。 什么是协程? 协程是用于合作式多任务处理的子程序(或函数…...

QCC51XX-QCC30XX系列开发教程(实战篇) 之 12.1-空间音频相关模块的概述

查看全部教程开发请点击:全网最全-QCC51xx-QCC30xx(TWS)系列从入门到精通开发教程汇总(持续更新中) ==================================================================== 版权归作者所有,未经允许,请勿转载。 ==========================================...

Servlet的生命周期

2023.10.18 WEB容器创建的Servlet对象,这些Servlet对象都会被放到一个集合当中(HashMap),这个集合当中存储了Servlet对象和请求路径之间的关系 。只有放到这个HashMap集合中的Servlet才能够被WEB容器管理,自己new的Ser…...

2.4 如何在FlinkSQL使用DataGen(数据生成器)

1、DataGen SQL 连接器 FLinkSQL中可以使用内置的DataGen SQL 连接器来生成测试数据 官网链接:DataGen SQL 连接器 2、随机数数据生成器 随机数数据生成器支持随机生成 char、varchar、binary、varbinary、string 类型的数据 它是一个无界流的数据生成器 -- TO…...

Gin + Ant Design Pro JWT认证

文章目录 一:介绍二:Gin JWT 后台1. Claims 定义2. 创建和解析Token3. Gin中间件编写4. 辅助函数 三:Ant Design Pro JWT认证四:Gin中间件和使用示范 一:介绍 JWT现在比较流行的认证方式,微服务中使用特别…...

canvas实现图片标注,绘制区域

使用canvas绘制通过多边形标注区域 AI视频项目中需要分析图片&#xff0c;需要前台绘制区域&#xff0c;后端获取坐标然后识别图像&#xff0c;通过canvas 获取点然后连线绘图 HEML代码段 <div class"areaDrawing"><img src"/assets/images/snapPhotos…...

SELECT COUNT(*) 会造成全表扫描吗?

前言 SELECT COUNT(*)会不会导致全表扫描引起慢查询呢&#xff1f; SELECT COUNT(*) FROM SomeTable 网上有一种说法&#xff0c;针对无 where_clause 的 COUNT(*)&#xff0c;MySQL 是有优化的&#xff0c;优化器会选择成本最小的辅助索引查询计数&#xff0c;其实反而性能…...

python考前复习(90题)

文章目录 1.Python特性的是( )。 A. 面向对象 B. 高可移植性 C. 开源、免费 2.临时改变Python语言安装源应当使用的选项是 –index-url 3.Python脚本文件的扩展名为( ) .py 4.安装Python语言的软件包使用的命令是&#xff08; &#xff09; pip install 5 . (单选题)以下哪项是…...

根据SpringBoot Guides完成进行示例学习(详细步骤)

目录 1.打开Spring | Guides官网&#xff0c;或者直接搜索springboot都可 2.选择要学习的内容 3.根据提示的网址&#xff0c;Git到本地 4.将文件用IDEA打开&#xff0c;根据教程完成示例&#xff0c;这里不做细致讲解 5.运行项目 6.在终端查看运行结果 以Scheduling Task…...

waf、yakit和ssh免密登录

WAF安全狗 脏数据适用于所有漏洞绕过waf&#xff0c;但是前提条件垃圾信息必须放在危险信息前&#xff0c;是不能打断原有数据包的结构&#xff0c;不能影响后端对数据包的解析。 以DVWA靶场文件上传为例 新建php文件 上传文件被安全狗拦截 使用bp抓包查看 在数据包Content-…...

【AIGC核心技术剖析】大型语言和视觉助手——LLaVA(论文+源码)

🔥 [新!LLaVA-1.5 在 11 个基准测试上实现了 SoTA,只需对原始 LLaVA 进行简单的修改,利用所有公共数据,在单个 1-A8 节点上在 ~100 天内完成训练,并超越使用数十亿级数据的方法。 LLaVA代表了一种新颖的端到端训练大型多模态模型,结合了视觉编码器和骆马 对于通用的视…...

IBM的WAS简介与基本使用手册

IBM的WAS简介与基本使用手册 1. 基本介绍 WebSphereApplication Server(简称WAS)是IBM的应用服务器 基本结构:单元(cell) ——> 多个节点(node) ——> 多个服务(server) ——> 多个应用(app) 单元是整个分布式网络中一个或多个节点的逻辑分组单元是一个配置概念, 是…...

Deno 快速入门

目录 1、简介 2、安装Deno MacOS下安装 Windows下安装 Linux 下安装 3、创建并运行TypeScript程序 4、内置Web API和Deno命名空间 5、运行时安全 6、导入JavaScript模块 7、远程模块和Deno标准库 8、使用deno.json配置您的项目 9、Node.js API和npm包 10、配置IDE…...

【计算机网络笔记】OSI参考模型基本概念

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…...

ConnectTimeout和ReadTimeout所代表的意义

ConnectTimeout和ReadTimeout所代表的意义 ConnectTimeout 指的是建立连接所用的时间&#xff0c;适用于网络状况正常的情况下&#xff0c;两端连接所用的时间。在java中&#xff0c;网络状况正常的情况下&#xff0c;例如使用HttpClient或者HttpURLConnetion连接时设置参数c…...

使用Python计算平面多边形间最短距离,数据需要从excel表格中导入

使用Python计算平面多边形间最短距离&#xff0c;数据需要从excel表格中导入&#xff0c; * 多边形种类包括&#xff08;圆形、矩形、六边形、五边形、跑道形/胶囊形&#xff09;&#xff0c; * Python代码需要使用gjk算法进行判断两个多边形间是否重叠&#xff0c; * 如果未重…...

华为数通方向HCIP-DataCom H12-831题库(多选题:1-20)

第01题 如图所示,路由器所有的接口开启OSPF,图中标识的ip地址为设备的Loopback0接口的IP地址,R1、R2,R3的Loopback0通告在区域1,R4的Loopback0通告在区域0、R5的Lopback0通告在区域2,下列哪些IP地址之间可以相互Ping通? A、10.0.3.3和10.0.5.5 B、10.0.4.4和10.0.2.2 …...

SEO的发展趋势会是什么样的

SEO的发展趋势会是什么样的 在互联网的快速发展中&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;技术一直是网站排名和流量增长的关键。随着技术的不断进步&#xff0c;SEO的发展趋势也在不断演变。未来SEO的发展趋势会是什么样的呢&#xff1f;本文将从多个角度探讨这…...

C++ 性能评测工程:基于 Google Benchmark 的 C++ 函数级性能基准测试方法论

各位技术同仁&#xff0c;下午好&#xff01;今天&#xff0c;我们将深入探讨一个在C开发中至关重要的话题&#xff1a;C 函数级性能基准测试。尤其是在追求极致性能的C世界里&#xff0c;仅仅依靠经验和直觉来优化代码是远远不够的。我们需要一套科学、严谨的方法论来量化和评…...

AI营销SaaS榜单评测:原圈科技如何助力品牌客户破局增长?

本文深度探讨AI营销行业趋势与SaaS产品评选标准。在众多解决方案中&#xff0c;原圈科技的AI营销SaaS平台凭借其领先的技术底层能力、产品成熟度及客户成功案例&#xff0c;在市场适配度与服务落地性等多个维度下表现突出&#xff0c;被普遍视为企业实现精细化营销升级的有力选…...

STM32除零运算不崩溃的机制与配置解析

1. STM32单片机除零运算不崩溃的底层机制解析 在嵌入式开发领域&#xff0c;STM32系列单片机因其出色的性能和丰富的外设资源而广受欢迎。许多从传统PC平台转向嵌入式开发的工程师都会发现一个有趣的现象&#xff1a;在STM32上执行除零操作时&#xff0c;程序竟然不会像在PC上那…...

Open-Shell-Menu:让Windows界面回归高效与个性化的开源解决方案

Open-Shell-Menu&#xff1a;让Windows界面回归高效与个性化的开源解决方案 【免费下载链接】Open-Shell-Menu Classic Shell Reborn. 项目地址: https://gitcode.com/gh_mirrors/op/Open-Shell-Menu 当项目经理王工在Windows 11电脑上第5次点击"所有应用"按钮…...

485总线硬件设计必看:电平匹配、TVS防护,还有exmodbus库快速上手

RS485是工业物联网的标配通信接口。合宙Air780EHV系列Cat.1模组凭借强大外设扩展能力&#xff08;LCD、摄像头、以太网、CAN等&#xff09;和LuatOS高效开发环境&#xff0c;支持TCP/MQTT/HTTP/Modbus等主流协议&#xff0c;是工业场景的高性价比之选。 本文聚焦RS485实战&…...

小型纯电动汽车轮毂电机及大角度转向系统的数字化设计【含catia、solidworks、CAD图纸、答辩PPT、说明书】

小型纯电动汽车轮毂电机与大角度转向系统的数字化设计&#xff0c;是新能源汽车领域的关键技术突破方向。轮毂电机通过将驱动装置集成于车轮内部&#xff0c;实现了动力传递路径的简化与能量利用效率的提升&#xff0c;其分布式驱动特性使车辆具备更灵活的扭矩分配能力&#xf…...

【手把手教学】使用stitch 生成ui图,导入figma,再用codebuddy生成工程代码

目录 一.stich使用 1.1 关键词生成 1.2 生成ui图 1.3 导出figma​编辑 二. codebuddy使用 ​编辑2.1打开figma ​编辑 2.2 复制ui到设计面板 2.3生成工程代码 三. 结语 一.stich使用 stich官网地址 Google Stitch 是 Google Labs 推出的、基于 Gemini 大模型驱动的A…...

告别重复编码:用Copaw结合快马平台,自动化生成你的常用工具模块

作为一名经常需要整理会议纪要的开发者&#xff0c;我一直在寻找能提升效率的工具。最近尝试用Copaw结合InsCode(快马)平台做了一个会议纪要自动生成器&#xff0c;效果出乎意料地好。整个过程几乎没写代码&#xff0c;却实现了核心功能&#xff0c;分享下具体实现思路&#xf…...

DevOps实践:如何让开发、测试、运维不再“打架”?

质量不再是孤岛在追求快速迭代的现代软件开发中&#xff0c;开发、测试与运维团队之间的隔阂与摩擦&#xff0c;常常被戏称为“部门战争”。开发团队渴望快速交付新功能&#xff0c;测试团队需要足够的时间来保障质量&#xff0c;而运维团队则首要追求系统的稳定与可靠。当发布…...