工厂方法模式和抽象工厂方法模式的battle

news2025/6/10 12:32:05

1.案例直接上手

在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂:

下面的这个是我们的这个案例里面涉及到的接口和对应的实现类:

两个发送的方式,一个实现类是使用的邮件的形式,一个实现类使用的短信的方式

image-20250607212502666

下面的这个是我们的工厂,里面有一个方法,负责生产我们的对象:我们使用上面定义的接口进行返回值的接受,因为我们的这个返回值可能是不同的实现类,我们使用他们的共同实现的接口作为返回值的类型;

下面的这个代码的逻辑其实也是非常的简单,就是我们的这个输入的参数类型和我们的邮件一样,这个时候我们创建一个邮件的对象,如果和消息一样,我们创建的就是消息类型的这个对象,否则我们直接返回null即可;

image-20250607212719989

我们写一个测试类进行测试:传入这个mail参数,这个时候返回的就是我们的mail类型对象,调用里面的send方法;

image-20250607212924786

下面的这个是输出的结果,相信大家是很容易理解的:

image-20250607213019705

2.总结思考

上面的这个案例里面,我们定义了一个工厂,但是这个实现的效果显的很low,为什么这样说,因为这个过程我们两行代码就可以搞定;

我们可以直接创建一个mailSender对象,直接调用方法,岂不是更爽???

image-20250607213125368

实现的这个输出的效果完全一致,没有任何的区别:

image-20250607213223407

那么这样的话,我就有问题了,我们的这个工厂方法的优势体现在哪里呢,我们是不是不需要学习这个设计模式了呢,答案肯定是否定的,下面我们开始进行延伸,展示一下这个工厂的优势:

3.工厂的优势

如果这个时候创建200个对象,上面的两个做法的区别其实也不是很大,工厂是produce创建对象,而普通方法是直接new对象即可,调用对应的方法;

可见,这个情境下,我们的工厂方法仍然没有凸显自己的优势,但是如果我告诉你,每一次创建对象之前,我们需要打印“我喜欢学习设计模式”,阁下又应该如何应对呢;

使用普通的方法创建对象,当需要打印这句话的需求提出之后,我们每一次创建对象,都需要去打印这句话,200个对象需要打印200次,这样写的代码就非常的不美观,因为这个重复的内容太多了;

image-20250607213600602

这个时候,我们的工厂方法就凸显了自己的优势:我们只需要在这个工厂方法里面添加一句话,这个时候我们的这个所有的主函数里面的对象调用这个produce的时候就可以打印结果了,而不需要重复200次,这就是提升;从200遍到1遍,这个就提升了不少;

image-20250607213749956

如果这个时候客户又让你把那句话删除掉,这个时候工厂方法只需要删除一个地方,而我们的普通方法全部需要删除;

工厂方法:需要大量的创建对象的时候,使用工厂方法,提高代码的可维护性;

如果我们需要更多的实现类,我们的这个工厂方法也是会凸显优势的,方便对于这个实现类的管理;

4.多个工厂方法的改进

即使如此,我们使用了工厂模式,上面的这个代码依然是可以进行优化和改进的,如下所示,如果我们在这个测试类里面把这个参数传递错误了,对吧,我们的这个用户不小心在这个参数里面mail后面多加上了一个字符,这个时候就会出现无法对应的情况;

image-20250608104728909

下面的这个就是出现的异常,因为我们使用null调用这个send方法了,我们没有找到对应的mail或者是这个sms,这个时候s接收到的就是null,然后使用这个null调用我们的方法肯定就是不可取的了;

image-20250608104903949这个时候,就不得不提我们的这个多个工厂方法了,如下所示:增加工厂方法,意味着我们可以直接调用这个增加的工厂方法:

image-20250608110115363

这样的话,我们的测试类里面不需要进行这个参数的传递的过程,而是可以直接进行我们的新的方法的调用,这样就可以杜绝上面的那个参数传递错误的情况,而是直接调用对应的方法即可:

image-20250608110246072

5.静态工厂方法

上面的这个例子,我们需要先创建对象,然后去调用里面的相关的方法,这个时候我们可以继续优化,把原来的这个换成我们的静态的方法,这样就可以直接使用我们的类调用相关的方法即可,不需要进行这个new对象的操作;

image-20250608110904964

然后我们的这个测试类里面可以直接调用方法,不用创建对象,这个就是我们的静态方法的好处:

image-20250608111012478

6.抽象工厂方法模式

接下来,我们继续扩展,这个时候,如果我们需要在原来的发送邮件,发送信息的基础上面,添加这个发送包裹,我们会如何修改;

如果使用原来的方法,就需要在我们的工厂里面增加方法,然后去定义一个包裹类,实现我们原来定义的接口,但是这样做就违反了我们的开闭原则(测试之后不要再原来的基础上进行修改,可以增加,但是不要动原来的代码);

因此,我们引入了下面的这个抽象工厂方法:

通过下面的这个类图你可以是可以看出来的,我们的这个抽象工厂方法模式在原来的基础上进行了二次封装,定义了新的接口,两个工厂:

1)原来是一个工厂里面两个方法,我们需要增加包裹发送方式的时候,需要在工厂里面添加方法,违反了开闭原则;

2)抽象工厂方法里面,我们定义两个工厂,一个发送方式对应一个工厂,我们需要增加这个新的发送方式的时候,原来的代码都不需要变化,直接添加新的工厂里面实现这个方法即可;

3)这样的话,我们的抽象工厂方法就解决了我们的简单工厂方法的这个违反了开闭原则的问题,提高了代码的封装性和可扩展性;

image-20250608111921886
样的话,我们的抽象工厂方法就解决了我们的简单工厂方法的这个违反了开闭原则的问题,提高了代码的封装性和可扩展性;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2406621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙Navigation路由导航-基本使用介绍

1. Navigation介绍 Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(Nav…

CMS内容管理系统的设计与实现:多站点模式的实现

在一套内容管理系统中,其实有很多站点,比如企业门户网站,产品手册,知识帮助手册等,因此会需要多个站点,甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…

ZYNQ学习记录FPGA(二)Verilog语言

一、Verilog简介 1.1 HDL(Hardware Description language) 在解释HDL之前,先来了解一下数字系统设计的流程:逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端,在这个过程中就需要用到HDL,正文…

Java中HashMap底层原理深度解析:从数据结构到红黑树优化

一、HashMap概述与核心特性 HashMap作为Java集合框架中最常用的数据结构之一,是基于哈希表的Map接口非同步实现。它允许使用null键和null值(但只能有一个null键),并且不保证映射顺序的恒久不变。与Hashtable相比,Hash…

【记录坑点问题】IDEA运行:maven-resources-production:XX: OOM: Java heap space

问题:IDEA出现maven-resources-production:operation-service: java.lang.OutOfMemoryError: Java heap space 解决方案:将编译的堆内存增加一点 位置:设置setting-》构建菜单build-》编译器Complier

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统

核心速览 研究背景 ​​研究问题​​:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…

【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录

#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…

五、jmeter脚本参数化

目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …

python基础语法Ⅰ

python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…

C++11 constexpr和字面类型:从入门到精通

文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…

EEG-fNIRS联合成像在跨频率耦合研究中的创新应用

摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…

C++中vector类型的介绍和使用

文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)

漏洞概述 漏洞名称:Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号:CVE-2023-25194 CVSS评分:8.8 影响版本:Apache Kafka 2.3.0 - 3.3.2 修复版本:≥ 3.4.0 漏洞类型:反序列化导致的远程代…

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:

RabbitMQ 各类交换机

为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息​​:将消息…

高保真组件库:开关

一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…

未授权访问事件频发,我们应当如何应对?

在当下,数据已成为企业和组织的核心资产,是推动业务发展、决策制定以及创新的关键驱动力。然而,未授权访问这一隐匿的安全威胁,正如同高悬的达摩克利斯之剑,时刻威胁着数据的安全,一旦触发,便可…

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!

多连接 BLE 怎么设计服务不会乱?分层思维来救场! 作者按: 你是不是也遇到过 BLE 多连接时,调试现场像网吧“掉线风暴”? 温度传感器连上了,心率带丢了;一边 OTA 更新,一边通知卡壳。…

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…