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)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

旨在将数据结构与在该数据结构上执行的操作分离,从而使得添加新的操作变得更容易,而无需修改数据结构本身。

使用场景
当需要对一个对象结构中的对象执行多种不同的且不相关的操作时,尤其是这些操作需要避免"污染"对象类本身。
实现方式
定义访问者接口:声明一系列访问方法,一个访问方法对应数据结构中的一个元素类。
创建具体访问者:实现访问者接口,为每个访问方法提供具体实现。
定义元素接口:声明一个接受访问者的方法。
创建具体元素:实现元素接口,每个具体元素类对应数据结构中的一个具体对象

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用反向代理编写HTTP抓包工具——可视化界面

手写HTTP抓包工具——可视化界面 项目描述语言golang可视化fynev2功能代理抓包、重发、记录 目录 1. 示例1.1 主界面1.2 开启反向代理1.3 抓包1.4 历史记录1.5 重发 2. 核心代码2.1 GUI2.1 抓包 3. 结语3.1 传送门 1. 示例 1.1 主界面 1.2 开启反向代理 1.3 抓包 1.4 历史记录…

docker 基本用法及跨平台使用

一、Docker的优点 docker 主要解决的问题就是程序开发过程中编译和部署中遇到的环境配置的问题。 1.1 Docker与其他虚拟机层次结构的区别** 运行程序重点关注点在于环境。 VM虚拟机是基于Hypervisor虚拟化服务运行的。 Docker是基于内核的虚拟化技术实现的。 1.2 Docker的技…

FPGA国内”薪“赛道-在医疗领域的应用

mian 免 ze 责 sheng 声 ming 明 以下观点仅代表个人观点&#xff0c;不代表任何公司或者行业 从下游应用市场来看&#xff0c;通信和工业市场份额位居FPGA芯片一二位&#xff0c;同时通信市场份额有望持续提升。但是目前通信和工业市场趋于稳定&#xff0c;FPGA厂商一直推AI市…

安当透明加密(TDE)助力企业建立可信赖的数据环境

​​​​​​​ 透明加密是一种特殊的加密方法&#xff0c;它允许数据在存储或传输过程中自动进行加密和解密&#xff0c;而用户并不需要知道加密过程。这种技术对用户来说是“透明的”&#xff0c;因为它不会改变用户的日常操作习惯&#xff0c;加密和解密过程在后台自动进行…

[Redis]缓存常见问题解决(缓存穿透、击穿、雪崩一文解决!通俗易懂、代码实战!手把手教你解决缓存问题三兄弟!)

Redis常见问题解决 要求 只用一种缓存技术&#xff0c;从实验点中挑一些试验进行试验原理。 1.缓存原理 目标&#xff1a;理解缓存的基本原理和工作机制。 实验步骤&#xff1a; 阅读各缓存技术机制的文档和官方资料。实现一个简单的应用程序&#xff0c;模拟数据的读写和…

Web渗透-CSRF跨站请求伪造

跨站请求伪造&#xff08;Cross-Site Request Forgery&#xff0c;CSRF&#xff09;是一种网络攻击&#xff0c;通过利用受害者的身份认证状态在不知情的情况下执行恶意操作。通常&#xff0c;这种攻击会诱使用户点击恶意链接或访问一个特制的网站&#xff0c;从而触发不被用户…

上交商汤联合提出一种虚拟试穿的创新方法,利用自监督视觉变换器 (ViT) 和扩散模型

上交&商汤联合提出一种虚拟试穿的创新方法&#xff0c;利用自监督视觉变换器 (ViT) 和扩散模型&#xff0c;强调细节增强&#xff0c;通过将 ViT 生成的局部服装图像嵌入与其全局对应物进行对比。虚拟试穿体验中细节的真实感和精确度有了显着提高&#xff0c;大大超越了现有…

创建OpenWRT虚拟机

环境&#xff1a;Ubuntu 2204&#xff0c;VM VirtualBox 7.0.18 安装必备软件包&#xff1a; sudo apt update sudo apt install subversion automake make cmake uuid-dev gcc vim build-essential clang flex bison g gawk gcc-multilib g-multilib gettext git libncurses…

vulnhub靶场之FunBox-11

一.环境搭建 1.靶场描述 As always, its a very easy box for beginners. Add to your /etc/hosts: funbox11 This works better with VirtualBox rather than VMware. 2.靶场下载 https://www.vulnhub.com/entry/funbox-scriptkiddie,725/ 3.靶场启动 二.信息收集 1.寻找靶…

数学建模系列(3/4):典型建模方法

目录 引言 1. 回归分析 1.1 线性回归 基本概念 Matlab实现 1.2 多元回归 基本概念 Matlab实现 1.3 非线性回归 基本概念 Matlab实现 2. 时间序列分析 2.1 时间序列的基本概念 2.2 移动平均 基本概念 Matlab实现 2.3 指数平滑 基本概念 Matlab实现 2.4 ARIM…

Vue 自定义ElementUI的Loading效果

import { loadingText, messageDuration } from "/settings";import { Loading } from "element-ui"; // loadingText、messageDuration 这两个参数我是调的公共配置文件,按自己需求来 const install (Vue, opts {}) > {/* 全局多彩Loading加载层 *…

Open3D点云处理学习

Color ICP Colored point cloud registration — Open3D 0.11.0 documentation Colored point cloud registration - Open3D 0.18.0 documentation 展示了使用color-icp结果 对比gicp错误处理结果 intel自己的论文 Colored Point Cloud Registration Revisited 优化方程 参…

web版的数字孪生,选择three.js、unity3D、还是UE4

数字孪生分为客户端版和web端版&#xff0c;开发引擎多种多用&#xff0c;本文重点分析web端版采用哪种引擎最合适&#xff0c; 贝格前端工场结合实际经验和网上主流说法&#xff0c;为您讲解。 一、数字孪生的web版和桌面版 数字孪生的Web版和桌面版是数字孪生技术在不同平台…

昇思25天学习打卡营第4天|网络构建|函数式自动微分

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) 网络构建 神经网络模型是由神经网络层和Tensor操作构成的&#xff0c;mindspore.nn提供了常见神经网络层的实现&#xff0c;在MindSpore中&#xff0c;Cell类是构建所有网络的基类&#xff0c;也…

29-Linux--守护进程

一.基础概念 1.守护进程&#xff1a;精灵进程&#xff0c;在后台为用户提高服务&#xff0c;是一个生存周期长&#xff0c;通常独立于控制终端并且周期性的执行任务火处理事件发生 2.ps axj&#xff1a;查看守护进程 3.进程组&#xff1a;多个进程的集合&#xff0c;由于管理…

快捷方式(lnk)--加载HTA-CS上线

免责声明:本文仅做技术交流与学习... 目录 CS: HTA文档 文件托管 借助mshta.exe突破 本地生成lnk快捷方式: 非系统图标路径不同问题: 关于lnk的上线问题: CS: HTA文档 配置监听器 有效载荷---->HTA文档--->选择监听器--->选择powershell模式----> 默认生成一…

Python神经影像数据的处理和分析库之nipy使用详解

概要 神经影像学(Neuroimaging)是神经科学中一个重要的分支,主要研究通过影像技术获取和分析大脑结构和功能的信息。nipy(Neuroimaging in Python)是一个强大的 Python 库,专门用于神经影像数据的处理和分析。nipy 提供了一系列工具和方法,帮助研究人员高效地处理神经影…

Desoutter智能拧紧中枢Connect过压维修

马头智能拧紧中枢过压维修是马头拧紧设备维护中的重要环节。当出现马头拧紧设备中枢过压现象时&#xff0c;会导致设备性能下降&#xff0c;甚至损坏设备&#xff0c;因此及时对过压中枢进行维修是保障设备正常运转的关键。 Desoutter电动螺丝刀控制器过压的原因可能有很多&am…

emqx5.6.1 数据、配置备份与迁移

EMQX 支持导入和导出的数据包括&#xff1a; EMQX 配置重写的内容&#xff1a; 认证与授权配置规则、连接器与 Sink/Source监听器、网关配置其他 EMQX 配置内置数据库 (Mnesia) 的数据 Dashboard 用户和 REST API 密钥客户端认证凭证&#xff08;内置数据库密码认证、增强认证…

五十六、openlayers官网示例Magnify解析——在地图上实现放大镜效果

官网demo地址&#xff1a; Magnify 这篇讲了如何在地图上添加放大镜效果。 首先加载底图 const layer new TileLayer({source: new StadiaMaps({layer: "stamen_terrain_background",}),});const container document.getElementById("map");const map …