Java23种设计模式(四)
1、备忘录模式
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象,备忘录模式属于行为型模式。
备忘录模式允许在不破坏封装性的前提下,捕获和恢复对象的内部状态。
实现方式
- 创建备忘录类:用于存储和封装对象的状态。
- 创建发起人角色:负责创建备忘录,并根据需要恢复状态。
- 创建备忘录管理类(可选):负责管理所有备忘录对象。
2、观察者模式
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
观察者模式解决的是一个对象状态改变时,如何自动通知其他依赖对象的问题,同时保持对象间的低耦合和高协作性。
2.1、实现方式
- 定义观察者接口:包含一个更新方法。
- 创建具体观察者:实现观察者接口,定义接收到通知时的行为。
- 定义主题接口:包含添加、删除和通知观察者的方法。
- 创建具体主题:实现主题接口,管理观察者列表,并在状态改变时通知它们。
2.2、应用实例
拍卖系统:拍卖师作为主题,竞价者作为观察者,拍卖价格更新时通知所有竞价者。
2.3、优点
- 抽象耦合:观察者和主题之间是抽象耦合的。
- 触发机制:建立了一套状态改变时的触发和通知机制。
2.4、缺点
- 性能问题:如果观察者众多,通知过程可能耗时。
- 循环依赖:可能导致循环调用和系统崩溃。
- 缺乏变化详情:观察者不知道主题如何变化,只知道变化发生。
2.4、使用建议
在需要降低对象间耦合度,并且对象状态变化需要触发其他对象变化时使用。
考虑使用Java内置的观察者模式支持类,如java.util.Observable和java.util.Observer。
2.5、注意事项
避免循环引用:注意观察者和主题之间的依赖关系,避免循环引用。
异步执行:考虑使用异步通知避免单点故障导致整个系统卡壳。
2.6、实现
观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。
ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。
步骤 1
创建 Subject 类。
Subject.java
import java.util.ArrayList;
import java.util.List;public class Subject {private List<Observer> observers = new ArrayList<Observer>();private int state;public int getState() {return state;}public void setState(int state) {this.state = state;notifyAllObservers();}public void attach(Observer observer){observers.add(observer); }public void notifyAllObservers(){for (Observer observer : observers) {observer.update();}}
}
步骤 2
创建 Observer 类。
Observer.java
public abstract class Observer {protected Subject subject;public abstract void update();
}
步骤 3
创建实体观察者类。
BinaryObserver.java
public class BinaryObserver extends Observer{public BinaryObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); }
}
OctalObserver.java
public class OctalObserver extends Observer{public OctalObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); }
}
HexaObserver.java
public class HexaObserver extends Observer{public HexaObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); }
}
步骤 4
使用 Subject 和实体观察者对象。
ObserverPatternDemo.java
public class ObserverPatternDemo {public static void main(String[] args) {Subject subject = new Subject();new HexaObserver(subject);new OctalObserver(subject);new BinaryObserver(subject);System.out.println("First state change: 15"); subject.setState(15);System.out.println("Second state change: 10"); subject.setState(10);}
}
步骤 5
执行程序,输出结果:
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
3、状态模式
在状态模式(State Pattern)中,类的行为是基于它的状态改变的,这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
状态模式允许对象在内部状态改变时改变其行为,使得对象在不同的状态下有不同的行为表现。通过将每个状态封装成独立的类,可以避免使用大量的条件语句来实现状态切换。
3.1、使用场景
当代码中存在大量条件语句,且这些条件语句依赖于对象的状态时。
3.2、使用建议
当对象的行为随状态改变而变化时,考虑使用状态模式。
状态模式适用于替代复杂的条件或分支语句。
3.3、注意事项
状态模式适用于状态数量有限(通常不超过5个)的情况。
谨慎使用,以避免系统变得过于复杂。
4、空对象模式
在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。
在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。
使用一个空对象代替 null 值,这个空对象实现了相同的接口,但对请求不做任何操作或提供默认操作。
5、策略模式
在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
将每个算法封装起来,使它们可以互换使用。
5.1、应用实例
- 锦囊妙计:每个锦囊代表一个策略,包含不同的计策。
- 旅行方式选择:骑自行车、坐汽车等,每种方式都是一个可替换的策略。
- Java AWT的LayoutManager:不同的布局管理器实现了相同的接口,但提供了不同的布局算法。
5.2、优点
- 算法切换自由:可以在运行时根据需要切换算法。
- 避免多重条件判断:消除了复杂的条件语句。
- 扩展性好:新增算法只需新增一个策略类,无需修改现有代码。
5.3、缺点
- 策略类数量增多:每增加一个算法,就需要增加一个策略类。
- 所有策略类都需要暴露:策略类需要对外公开,以便可以被选择和使用。
如果系统中策略类数量过多,考虑使用其他模式或设计技巧来解决类膨胀问题。
6、模板模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
在父类中定义了算法的骨架,并允许子类在不改变算法结构的前提下重定义算法的某些特定步骤。
6.1、实现方式
定义抽象父类:包含模板方法和一些抽象方法或具体方法。
实现子类:继承抽象父类并实现抽象方法,不改变算法结构。
6.2、优点
- 封装不变部分:算法的不变部分被封装在父类中。
- 扩展可变部分:子类可以扩展或修改算法的可变部分。
- 提取公共代码:减少代码重复,便于维护。
为了防止恶意修改,模板方法通常使用final关键字修饰,避免被子类重写。
6.3、实现
我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法。
TemplatePatternDemo,我们的演示类使用 Game 来演示模板模式的用法。
步骤 1
创建一个抽象类,它的模板方法被设置为 final。
Game.java
public abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();//模板public final void play(){//初始化游戏initialize();//开始游戏startPlay();//结束游戏endPlay();}
}
步骤 2
创建扩展了上述类的实体类。
Cricket.java
public class Cricket extends Game {@Overridevoid endPlay() {System.out.println("Cricket Game Finished!");}@Overridevoid initialize() {System.out.println("Cricket Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Cricket Game Started. Enjoy the game!");}
}
Football.java
public class Football extends Game {@Overridevoid endPlay() {System.out.println("Football Game Finished!");}@Overridevoid initialize() {System.out.println("Football Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Football Game Started. Enjoy the game!");}
}
步骤 3
使用 Game 的模板方法 play() 来演示游戏的定义方式。
TemplatePatternDemo.java
public class TemplatePatternDemo {public static void main(String[] args) {Game game = new Cricket();game.play();System.out.println();game = new Football();game.play(); }
}
步骤 4
执行程序,输出结果:
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
7、访问者模式
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
旨在将数据结构与在该数据结构上执行的操作分离,从而使得添加新的操作变得更容易,而无需修改数据结构本身。
使用场景
当需要对一个对象结构中的对象执行多种不同的且不相关的操作时,尤其是这些操作需要避免"污染"对象类本身。
实现方式
定义访问者接口:声明一系列访问方法,一个访问方法对应数据结构中的一个元素类。
创建具体访问者:实现访问者接口,为每个访问方法提供具体实现。
定义元素接口:声明一个接受访问者的方法。
创建具体元素:实现元素接口,每个具体元素类对应数据结构中的一个具体对象
相关文章:

Java23种设计模式(四)
1、备忘录模式 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象,备忘录模式属于行为型模式。 备忘录模式允许在不破坏封装性的前提下,捕获和恢复对象的内部状态。 实现方式 创建备忘录…...

HTML静态网页成品作业(HTML+CSS)——故宫介绍网页(4个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有4个页面。 二、作品演示 三、代…...
Zookeeper:客户端命令行操作
文章目录 一、help二、ls path三、create四、get path五、set六、stat七、delete八、deleteall 一、help 显示所有操作命令。 二、ls path 使用ls命令来查看当前znode的子节点[可监听] w:监听子节点变化。s:附加次级信息。 三、create 普通创建&am…...
区块链技术介绍和用法
区块链技术是一种分布式账本技术,可以记录和存储一系列交易信息,并通过密码学算法保证信息的安全性和不可篡改性。区块链技术的核心概念是“区块”和“链”。 每个区块包含了一部分交易信息,以及一个指向上一个区块的哈希值。当新的交易发生…...

Upload-Labs-Linux1 使用 一句话木马
解题步骤: 1.新建一个php文件,编写内容: <?php eval($_REQUEST[123]) ?> 2.将编写好的php文件上传,但是发现被阻止,网站只能上传图片文件。 3.解决方法: 将php文件改为图片文件(例…...

从 Hadoop 迁移,无需淘汰和替换
我们仍然惊讶于有如此多的客户来找我们,希望从HDFS迁移到现代对象存储,如MinIO。我们现在以为每个人都已经完成了过渡,但每周,我们都会与一个决定进行过渡的主要、高技术性组织交谈。 很多时候,在这些讨论中ÿ…...

深度学习:从理论到应用的全面解析
引言 深度学习作为人工智能(AI)的核心技术之一,在过去的十年中取得了显著的进展,并在许多领域中展示了其强大的应用潜力。本文将从理论基础出发,探讨深度学习的最新进展及其在各领域的应用,旨在为读者提供全…...

【02】区块链技术应用
区块链在金融、能源、医疗、贸易、支付结算、证券等众多领域有着广泛的应用,但是金融依旧是区块链最大且最为重要的应用领域。 1. 区块链技术在金融领域的应用 1.2 概况 自2019年以来,国家互联网信息办公室已发布八批境内区块链信息服务案例清单&#…...
一篇文章搞懂残差网络算法
残差网络(Residual Network,简称ResNet)是一种深度学习架构,它在2015年由微软研究院的Kaiming He等四位作者提出。ResNet的提出是为了解决深度神经网络训练中的梯度消失和梯度爆炸问题,以及随着网络层数增加而出现的性能退化问题。本文将详细介绍残差网络算法的定义、产生…...

网络安全:Web 安全 面试题.(SQL注入)
网络安全:Web 安全 面试题.(SQL注入) 网络安全面试是指在招聘过程中,面试官会针对应聘者的网络安全相关知识和技能进行评估和考察。这种面试通常包括以下几个方面: (1)基础知识:包括网络基础知识、操作系…...

XSS学习(绕过)
学习平台:xss.tesla-space.com XSS学习(绕过) level1level2level3level4level5level6level7level8level9level10level11level12level13level14 level1 应该没有过滤 https://xss.tesla-space.com/level1.php?name<script>alert(1);&…...
深信服2024笔试
一 :服务器 小明是一名公司的IT运维工程师,负责管理公司的IT系统。公司总共有两个配置相同的服务器A和B,各运行了若干个服务。现在小明发现两台服务器上运行的服务占用的内存总和不相等(假设每个服务占用内存是-个恒定正整数),打…...
IOS Swift 从入门到精通:闭包 第一部分
文章目录 创建基本闭包在闭包中接受参数从闭包返回值闭包作为参数尾随闭包语法 创建基本闭包 Swift 允许我们像使用字符串和整数等其他类型一样使用函数。这意味着您可以创建一个函数并将其分配给一个变量,使用该变量调用该函数,甚至可以将该函数作为参…...

解两道四年级奥数题(等差数列)玩玩
1、1~200这200个连续自然数的全部数字之和是________。 2、2,4,6,……,2008这些偶数的所有各位数字之和是________。 这两道题算易错吧,这里求数字之和,比如124这个数的全部数字之和是1247。 …...

深入理解Python中的并发与异步的结合使用
在上一篇文章中,我们讨论了异步编程中的性能优化技巧,并简单介绍了trio和curio库。今天,我们将深入探讨如何将并发编程与异步编程结合使用,并详细讲解如何利用trio和curio库优化异步编程中的性能。 文章目录 并发与异步编程的区…...

如何将 ChatGPT 集成到你的应用中
在当今快速发展的技术环境中,将人工智能聊天解决方案集成到你的应用程序中可以显著提升用户体验和参与度。OpenAI 的 ChatGPT 以其对话能力和高级语言理解而闻名,对于希望在其应用程序中实现智能聊天功能的开发人员来说是一个绝佳的选择。那我们今天就来…...
在 Swift 中,UILabel添加点击事件的方法
在 Swift 中,可以使用 UITapGestureRecognizer 给 UILabel 添加点击事件。以下是一个详细的步骤和示例代码: 1. 创建 UILabel 并添加到视图 在 Storyboard 或代码中创建一个 UILabel 并将其添加到视图中。 2. 启用 UILabel 的用户交互 默认情况下&am…...

indexedDB---掌握浏览器内建数据库的基本用法
1.认识indexedDB IndexedDB 是一个浏览器内建的数据库,它可以存放对象格式的数据,类似本地存储localstore,但是相比localStore 10MB的存储量,indexedDB可存储的数据量远超过这个数值,具体是多少呢? 默认情…...

【css】如何修改input选中历史选项后,自动填充的蓝色背景色
自动填充前: 自动填充后: 解决办法 方法一:设置背景透明(通过拉长过渡时间,和延迟过渡开始时间,掩盖input自动填充背景颜色) PS:注意,这个过渡效果会在你的delay tim…...
红队内网攻防渗透:内网渗透之内网对抗:网络通讯篇防火墙组策略入站和出站规则单层双层C2正反向上线解决方案
红队内网攻防渗透 1. 内网网络通讯1.1 防火墙策略-入站规则&出站规则&自定义1.1.1 防火墙默认入站&出站策略1.1.2 防火墙自定义入站&出站策略1.1.3 内网域防火墙同步策略1.2 防火墙限制1.2.1 防火墙限制端口1.2.2 防火墙限制协议1.2.2.1 防火墙协议入站限制1.2…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...