行为型设计模式(三)状态模式 备忘录模式

状态模式 State

1、什么是状态模式

状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类,将对象的行为包装在不同的状态类中,对象在运行时根据内部状态的改变而改变它的行为。

2、为什么使用状态模式

  1. 封装了转换规则:状态模式将每个状态的行为封装在一个类中,使得转换规则更加清晰,易于理解和维护。
  2. 减少条件语句:状态模式减少了对象中大量的条件语句,提高了代码的可读性和可维护性。
  3. 状态切换更加灵活:状态模式使得状态切换变得更加灵活,可以在运行时动态地改变对象的状态。

3、如何使用状态模式

设计实现一个电梯状态:开门、关门、上升、下降等

// 状态接口
interface ElevatorState {void open();void close();void up();void down();
}// 具体状态1:开门
class OpenState implements ElevatorState {@Overridepublic void open() {System.out.println("The door is already open.");}@Overridepublic void close() {System.out.println("Closing the door.");}@Overridepublic void up() {System.out.println("Cannot go up while the door is open.");}@Overridepublic void down() {System.out.println("Cannot go down while the door is open.");}
}// 具体状态2:关门
class CloseState implements ElevatorState {@Overridepublic void open() {System.out.println("Opening the door.");}@Overridepublic void close() {System.out.println("The door is already closed.");}@Overridepublic void up() {System.out.println("Going up.");}@Overridepublic void down() {System.out.println("Going down.");}
}// 上下文类,维护当前状态
class ElevatorContext {private ElevatorState currentState;// 设置当前状态void setCurrentState(ElevatorState currentState) {this.currentState = currentState;}// 调用状态的方法void open() {currentState.open();}void close() {currentState.close();}void up() {currentState.up();}void down() {currentState.down();}
}// 客户端代码
public class Client {public static void main(String[] args) {ElevatorContext elevator = new ElevatorContext();// 初始状态为关门elevator.setCurrentState(new CloseState());// 执行操作elevator.open();elevator.up();elevator.close();elevator.down();}
}

4、是否存在缺陷和不足

  1. 状态模式引入了多个状态类,有可能增加系统中类的数量。
  2. 如果状态切换的逻辑比较复杂,会增加状态模式的复杂度。

5、如何缓解缺陷和不足

  1. 如果实际业务场景中,存在相似的状态行为,建议考虑合并相似行为的状态,减少状态类的数量。
  2. 尽量简化状态切换的逻辑,保持状态模式的清晰性。

备忘录模式 Memento

1、什么是备忘录模式

备忘录模式允许对象在不暴露内部状态的情况下保存和恢复状态,通过将对象的状态保存到备忘录对象中,以便后续需要时恢复到该状态。

2、为什么使用备忘录模式

  1. 封装了对象状态:备忘录模式将对象的状态封装到备忘录中,使得对象的状态对外部是不可见的。
  2. 支持撤销和恢复:备忘录模式支持将对象恢复到之前的状态,从而实现撤销的功能。

3、如何使用备忘录模式

设计实现一个文本编辑器,用户可以输入文本并且可以随时保存编辑器的状态

// 备忘录类
class EditorMemento {private final String content;EditorMemento(String content) {this.content = content;}String getContent() {return content;}
}// 原发器类
class TextEditor {private StringBuilder content = new StringBuilder();// 创建备忘录EditorMemento createMemento() {return new EditorMemento(content.toString());}// 恢复备忘录void restoreMemento(EditorMemento memento) {this.content = new StringBuilder(memento.getContent());}// 修改文本内容void addText(String text) {content.append(text);}// 获取当前文本内容String getContent() {return content.toString();}
}// 负责人类
class EditorHistory {private Stack<EditorMemento> history = new Stack<>();// 将备忘录保存到历史记录中void save(EditorMemento memento) {history.push(memento);}// 从历史记录中获取最近的备忘录EditorMemento undo() {if (!history.isEmpty()) {return history.pop();}return null;}
}// 客户端代码
public class Client {public static void main(String[] args) {TextEditor editor = new TextEditor();EditorHistory history = new EditorHistory();// 输入文本editor.addText("Hello, ");System.out.println("Current Content: " + editor.getContent());// 保存备忘录history.save(editor.createMemento());// 输入更多文本editor.addText("World!");System.out.println("Current Content: " + editor.getContent());// 撤销操作,恢复到之前的状态editor.restoreMemento(history.undo());System.out.println("After Undo: " + editor.getContent());}
}

4、是否存在缺陷和不足

  1. 如果备忘录对象占用大量内存,可能会导致资源消耗较大。
  2. 如果原发器类的内部状态包含对其他对象的引用,备忘录模式无法完全保护这些对象的封装性。

5、如何缓解缺陷和不足

  1. 精简备忘录:如果备忘录对象占用大量内存,可以考虑设计更加精简的备忘录对象,只保存必要的状态。
  2. 深拷贝:如果原发器类的内部状态包含对其他对象的引用,可以使用深拷贝技术来复制这些对象,保护对象的封装性。

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

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

相关文章

【CentOS 7.9 分区】挂载硬盘为LVM操作实例

LVM与标准分区有何区别&#xff0c;如何选择 目录 1 小系统使用LVM的益处&#xff1a;2 大系统使用LVM的益处&#xff1a;3 优点&#xff1a;CentOS 7.9 挂载硬盘为LVM操作实例查看硬盘情况格式化硬盘创建PV创建VG创建LV创建文件系统并挂载自动挂载添加&#xff1a;注意用空格间…

树莓派,opencv,Picamera2利用舵机云台追踪特定颜色对象(PID控制)

一、需要准备的硬件 Raspiberry 4b两个SG90 180度舵机&#xff08;注意舵机的角度&#xff0c;最好是180度且带限位的&#xff0c;切勿选360度舵机&#xff09;二自由度舵机云台&#xff08;如下图&#xff09;Raspiberry CSI 摄像头 组装后的效果&#xff1a; 二、项目目标…

【C#】TimeSpan

文章目录 概述属性时间计算拓展来源 概述 TimeSpan结构&#xff1a;表示一个时间间隔。 它含有以下四个构造函数&#xff1a; TimeSpan(Int64)将 TimeSpan结构的新实例初始化为指定的刻度数。&#xff08;DateTime.Tick:是计算机的一个计时周期&#xff0c;单位是一百纳秒&…

flink使用sql-client-defaults.yml无效

希望在flink sql脚本启动时自动选择catalog&#xff0c;减少麻烦。于是乎配置sql-client-defaults.yaml&#xff1a; catalogs:- name: hive_catalogtype: icebergcatalog-type: hiveproperty-version: 1cache-enabled: trueuri: thrift://localhost:9083client: 5warehouse: …

02|用LangChain快速构建基于“易速鲜花”本地知识库的智能问答系统

02&#xff5c;用LangChain快速构建基于“易速鲜花”本地知识库的智能问答系统 项目及实现框架 我们先来整体了解一下这个项目。 项目名称&#xff1a;“易速鲜花”内部员工知识库问答系统。 项目介绍&#xff1a;“易速鲜花”作为一个大型在线鲜花销售平台&#xff0c;有自…

机器学习 | 概率图模型

见微知著&#xff0c;睹始知终。 见到细微的苗头就能预知事物的发展方向&#xff0c;能透过微小的现象看到事物的本质&#xff0c;推断结论或者结果。 概率模型为机器学习打开了一扇新的大门&#xff0c;将学习的任务转变为计算变量的概率分布。 实际情况中&#xff0c;各个变量…

HBase基础知识(一):HBase简介、HBase数据模型与基本架构

第1章HBase简介 1.1HBase定义 HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库。 1.2HBase数据模型 逻辑上&#xff0c;HBase的数据模型同关系型数据库很类似&#xff0c;数据存储在一张表中&#xff0c;有行有列。但从HBase的底层物理存储结构&#xff08;K-V&a…

如何直接使用别人的Python项目的虚拟环境

Cannot set up a python SDK at Python 3.10 (flaskTest) (2) (H:\WorkPlace\PyWorkPlace\flaskTest\flaskTest\venv\Scripts\python.exe). The SDK seems invalid 如何复制别人的虚拟环境 修改步骤 1. 修改pyvenv.cfg文件里的home和version 2. Scripts\activate以及Scripts\a…

ChatGPT一周年:开源语言大模型的冲击

自2022年末发布后&#xff0c;ChatGPT给人工智能的研究和商业领域带来了巨大变革。通过有监督微调和人类反馈的强化学习&#xff0c;模型可以回答人类问题&#xff0c;并在广泛的任务范围内遵循指令。在获得这一成功之后&#xff0c;人们对LLM的兴趣不断增加&#xff0c;新的LL…

Asp.Net Core 项目中常见中间件调用顺序

常用的 AspNetCore 项目中间件有这些&#xff0c;调用顺序如下图所示&#xff1a; 最后的 Endpoint 就是最终生成响应的中间件。 Configure调用如下&#xff1a; public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseD…

深入理解 Rust 中的容器类型及其应用

Rust 作为一种系统编程语言&#xff0c;提供了丰富的容器类型来处理各种数据结构和算法。这些容器类型不仅支持基本的数据存储和访问&#xff0c;还提供了高效的内存管理和安全性保障。本文将详细介绍 Rust 中的几种主要容器类型&#xff0c;包括它们的用法、特点和适用场景&am…

华为全屋wifi6蜂鸟套装标准

华为政企42 华为政企 目录 上一篇华为安防监控摄像头下一篇华为企业级无线路由器