Memento 备忘录模式

备忘录模式

  • 意图
  • 结构
  • 适用性
  • 实例
    • Java Web开发中的简单示例
      • Originator 类
      • Memento 类
      • Caretaker 类
    • 文本编辑器示例
      • 1. Originator (发起人) - `TextEditor`
      • 2. Memento (备忘录) - `TextMemento`
      • 3. Caretaker (负责人) - `History`
      • 4. 使用示例
      • 输出

备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不违反封装原则的情况下捕获并恢复对象的内部状态。下面我将为你概述备忘录模式的意图、结构以及适用性,并提供一个简单的结构图描述。

意图

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
这样以后就可以将该对象恢复到原先保存的状态。

结构

备忘录模式主要包含以下角色:

  • Memento(备忘录) 存储原发器对象的内部状态,原发器根据需要决定备忘录存储原发器的哪些内部状态;防止原发器以外的其他对象访问备忘录。

  • Originator(原发器) 创建一个备忘录,用于记录当前时刻它的内部状态;使用备忘录恢复内部状态。

  • Caretaker(管理者) 负责保存好备忘录;不能对备忘录的内容进行操作或检查。

  • Caretaker 负责保存和恢复备忘录(Memento),但不负责查看或修改备忘录的内容。

  • Originator 创建一个备忘录,用来存储它的内部状态,并且可以在需要时从备忘录恢复其状态。

  • Memento 存储了Originator的状态。它通常提供给Originator一个宽接口来存取所有数据,而给Caretaker一个窄接口,只允许获取备忘录对象而不允许对其进行操作。

适用性

  • 当必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
  • 如果直接暴露对象的内部细节会导致对象的封装性被破坏,那么可以使用备忘录模式。
  • 当一个应用程序需要提供“撤销”操作时,可以通过保存历史状态来实现,这时可以考虑使用备忘录模式。

备忘录模式通过引入一个中介者(Caretaker)来维护备忘录对象,从而避免了直接访问原始对象的状态信息,保持了良好的封装性。这种模式在很多场景中都非常有用,比如文本编辑器中的撤消/重做功能,或者游戏中的存档/读档机制等。

实例

在Java Web开发中,备忘录模式可以用于多种场景,尤其是在需要保存和恢复用户会话状态、表单数据或业务对象的状态时。以下是一些可能的应用案例:

  1. 购物车功能:在电子商务网站中,用户的购物车内容是一个不断变化的状态集合。使用备忘录模式可以保存用户当前的购物车状态,以便在用户离开后返回时能够恢复到之前的状态。

  2. 在线编辑器:如果有一个基于Web的富文本编辑器或者代码编辑器,你可以使用备忘录模式来实现撤销(undo)和重做(redo)功能。每次用户进行更改时,都可以创建一个备忘录来存储当前文档的状态。

  3. 游戏状态保存:对于基于Web的游戏,可以使用备忘录模式来保存游戏进度。玩家可以在任何时候保存游戏状态,并且在以后继续游戏时加载该状态。

  4. 配置管理:在企业级应用中,系统管理员可能会对应用程序进行不同的配置设置。使用备忘录模式可以保存这些配置状态,使得管理员可以轻松地回滚到之前的配置。

  5. 工作流中的步骤保存:在多步骤的工作流或向导界面中,每个步骤都有自己的状态。备忘录模式可以帮助用户在流程中的任意一步之间来回切换,同时保持每一步的数据完整性和一致性。

Java Web开发中的简单示例

假设我们有一个简单的在线问卷应用,用户可以填写一系列问题。为了提供更好的用户体验,我们可以允许用户暂停并稍后从上次停止的地方继续。

Originator 类

public class Questionnaire {private String currentQuestion;private Map<String, String> answers;public Questionnaire() {this.answers = new HashMap<>();}// 设置当前问题public void setCurrentQuestion(String question) {this.currentQuestion = question;}// 获取当前问题public String getCurrentQuestion() {return currentQuestion;}// 添加答案public void addAnswer(String question, String answer) {this.answers.put(question, answer);}// 创建备忘录public QuestionnaireMemento createMemento() {return new QuestionnaireMemento(this.currentQuestion, new HashMap<>(this.answers));}// 从备忘录恢复public void setMemento(QuestionnaireMemento memento) {this.currentQuestion = memento.getCurrentQuestion();this.answers = new HashMap<>(memento.getAnswers());}
}

Memento 类

public class QuestionnaireMemento {private final String currentQuestion;private final Map<String, String> answers;public QuestionnaireMemento(String currentQuestion, Map<String, String> answers) {this.currentQuestion = currentQuestion;this.answers = answers;}public String getCurrentQuestion() {return currentQuestion;}public Map<String, String> getAnswers() {return answers;}
}

Caretaker 类

public class SessionCaretaker {private QuestionnaireMemento memento;public void save(Questionnaire questionnaire) {this.memento = questionnaire.createMemento();}public void restore(Questionnaire questionnaire) {if (this.memento != null) {questionnaire.setMemento(memento);}}
}

在这个例子中,Questionnaire是Originator,它负责创建和恢复备忘录;QuestionnaireMemento是Memento,它存储了Questionnaire的状态;SessionCaretaker是Caretaker,它保存了备忘录但不修改它。通过这种方式,即使用户离开了页面,也可以通过保存的备忘录恢复他们的进度。

当然,让我们用一个简单的例子来说明备忘录模式。假设我们有一个文本编辑器应用,用户可以在其中输入文本,并且能够撤销和重做他们的更改。我们将使用备忘录模式来实现这一功能。

文本编辑器示例

1. Originator (发起人) - TextEditor

TextEditor类代表文本编辑器,它拥有当前的文本状态,并能创建和恢复备忘录。

public class TextEditor {private String text;public TextEditor() {this.text = "";}public void setText(String text) {this.text = text;}public String getText() {return text;}// 创建备忘录public TextMemento createMemento() {return new TextMemento(this.text);}// 从备忘录恢复public void setMemento(TextMemento memento) {this.text = memento.getState();}
}

2. Memento (备忘录) - TextMemento

TextMemento类用来存储TextEditor的状态。在这个例子中,它只包含文本内容。

public class TextMemento {private final String state;public TextMemento(String state) {this.state = state;}public String getState() {return state;}
}

3. Caretaker (负责人) - History

History类负责保存和管理一系列的备忘录对象。这可以用来实现撤销和重做功能。

import java.util.Stack;public class History {private Stack<TextMemento> mementos = new Stack<>();public void save(TextEditor editor) {mementos.push(editor.createMemento());}public void undo(TextEditor editor) {if (mementos.size() > 1) { // 确保至少有两个备忘录mementos.pop(); // 弹出最新的备忘录editor.setMemento(mementos.peek()); // 恢复到上一个状态} else if (mementos.size() == 1) {mementos.pop(); // 弹出唯一的备忘录editor.setText(""); // 清空文本}}
}

4. 使用示例

现在我们可以创建一个简单的控制台应用程序来展示如何使用这些类。

public class Main {public static void main(String[] args) {TextEditor editor = new TextEditor();History history = new History();editor.setText("Hello, world!");System.out.println("Initial text: " + editor.getText());// 保存当前状态history.save(editor);editor.setText("Goodbye, world!");System.out.println("Changed text: " + editor.getText());// 再次保存当前状态history.save(editor);// 撤销回到之前的状态history.undo(editor);System.out.println("After first undo: " + editor.getText());// 再次撤销回到最初的状态history.undo(editor);System.out.println("After second undo: " + editor.getText());}
}

输出

运行上述代码后,输出将是:

Initial text: Hello, world!
Changed text: Goodbye, world!
After undo: Hello, world!

这个例子展示了如何使用备忘录模式来实现简单的撤销功能。TextEditor是发起人,它能够创建和恢复自己的状态;TextMemento是备忘录,它存储了TextEditor的状态;而History是负责人,它保存了一系列的备忘录以便于撤销操作。通过这种方式,你可以轻松地扩展这个模型以支持更多的复杂功能,比如重做(redo)操作。

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

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

相关文章

导入项目时微信开发者工具如何自动识别项目APPID

一、需求 当我们在公司拉取小程序项目的时候&#xff0c;经常会在微信开发者工具中导入项目&#xff0c;需要我们手动输入自己的appid非常麻烦&#xff0c;我们可以用在导入项目的时候自动识别公司的appid 二、步骤 2.1 使用Hbuilder工具编译项目 编译成功后会有一个unpacka…

小语言模型介绍与LLM的比较

小模型介绍 小语言模型&#xff08;SLM&#xff09;与大语言模型&#xff08;LLM&#xff09;相比&#xff0c;具有不同的特点和应用场景。大语言模型通常拥有大量的参数&#xff08;如 GPT-3 拥有 1750 亿个参数&#xff09;&#xff0c;能够处理复杂的自然语言任务&#xff…

17.快递物流仓库管理系统(基于springboot和vue)

目录 1.系统的受众说明 2.系统详细设计 2.1 需求分析 2.2 系统功能设计 2.3 开发环境分析 ​​​​​​​2.4 E-R图设计 2.5 数据库设计 3. 系统实现 3.1 环境搭建 ​​​​​​​3.2 员工信息管理模块 3.3 销售订单信息管理模块 ​​​​​​​3.4 图表分析模块…

Shortcut Learning in In-Context Learning: A Survey

为我们的综述打一打广告&#xff0c;目前是初级版本&#xff0c;欢迎各位批评指正&#xff01;后续的论文列表、测评基准会在Github更新[/(ㄒoㄒ)/~~最近比较忙容许我拖一拖] 这里是arxiv链接&#xff1a;Linking!!! Abstract&#xff1a;捷径学习是指模型在实际任务中使用简单…

第三十四章 Vue路由进阶之声明式导航(导航高亮)

目录 一、导航高亮 1.1. 基于语法 1.2. 主要代码 二、声明式导航的两个类名 2.1. 声明式导航类名匹配方式 2.2. 声明式导航类名样式自定义 ​2.3. 核心代码 一、导航高亮 1.1. 基于语法 在Vue中通过VueRouter插件&#xff0c;我们可以非常简单的实现实现导航高亮效果…

第七部分:1. STM32之ADC实验--单通道实验

主要利用一个模拟量的电位器来实时改变电压值&#xff0c;通过STM32自带的ADC通道来采集这个数据&#xff0c;并打印出来&#xff01; 一句话&#xff0c;学完STM32&#xff0c;我就往南走&#xff0c;我的工资只有5000.~~~~Whappy

Ubuntu20.04两种安装及配置中文界面、输入法、换源、共享文件夹实现,及注意事项

虚拟机安装法 1、新建虚拟机&#xff0c;自定义下一步 任意指定路径 提高处理器数量能加快系统响应 完成以后不要运行&#xff0c;添加镜像文件 导入镜像文件&#xff0c;点击浏览 选择后打开->确认->运行虚拟机 出现这种情况就需要检查虚拟机的配置&#xff0c;操作系统…

记录解决vscode 登录leetcode中遇到的问题

1. 安装完 leetcode 点击sign in to leetcode 点击打开网站登录leetcode&#xff0c;发现网页无法打开。 解决办法&#xff1a;将leetcode.cn.js文件中的leetcode-cn.com路径都改成leetcode.cn 2. 继续点击 sign in to leetcode &#xff0c;选择使用账号登录&#xff0c;始…

docker镜像仓库实战

docker镜像仓库实战 搭建一个nginx服务基础知识(Web服务器)查找nginx镜像拉取镜像启动nginx镜像 搭建一个nginx服务 基础知识(Web服务器) Web 服务器&#xff0c;一般是指“网站服务器”&#xff0c;是指驻留于互联网上某种类型计算机的程序。Web 服务器可以向 Web 浏览器等客…

zabbix安装配置与使用

zabbix Zabbix的工作原理如下: 监控部分: Zabbix Agent安装在各个需要监控的主机上,它以主配置的时间间隔(默认60s)收集主机各项指标数据,如CPU占用率、内存使用情况等。 通讯部分: Agent会把收集的数据通过安全通道(默认10051端口)发送到Zabbix Server。Server会存储这些数…

CSS的三个重点

目录 1.盒模型 (Box Model)2.位置 (position)3.布局 (Layout)4.低代码中的这些概念 在学习CSS时&#xff0c;有三个概念需要重点理解&#xff0c;分别是盒模型、定位、布局 1.盒模型 (Box Model) 定义&#xff1a; CSS 盒模型是指每个 HTML 元素在页面上被视为一个矩形盒子。…

关于LLC知识23(频率越大变压器体积越小?)

为什么频率越高&#xff0c;同样的磁芯就可以用的更小&#xff1f; 变压器他负责的功能是 1、隔离 2、能量传递 这里主要是与能量传递有关 我们首先要知道&#xff0c;次级的输出功率一定的情况下&#xff0c;那么在一定的时段内消耗的能量就是一定的&#xff0c;比如1000W…

UE5.4 PCG Layered Biomes插件

B站学习链接 官方文档 一、PCGSpawn Preset&#xff1a;负责管理PCG要用到的植被资产有哪些 二、BiomesSettings&#xff1a;设置要使用的植被资产Layer、Spawn参数 1.高度Layer参数&#xff1a; 2.地形Layer&#xff1a;我这里用地形样条线绘制了一块地形Layer 绘制点和…

数字后端零基础入门系列 | Innovus零基础LAB学习Day8

###LAB15 Detail Routing for Signal Integrity, Timing, Power and Design for Yield 这个章节虽然标题有点长&#xff0c;但不要被它吓到&#xff0c;其实这个章节就是Innovus工具的绕线Routing。只不过这个阶段做Route不是仅仅是把所有的逻辑连接&#xff0c;用实际的金属层…

量化交易 股市技术指标

股市数据分类 股票数据根据信息来源和分析方法的不同&#xff0c;可以分为技术面数据和基本面数据。 技术面数据和基本面数据都是股票分析中重要的工具&#xff0c;它们提供了不同的视角和方法来评估股票的投资价值。投资者可以综合运用这两类数据&#xff0c;从技术面和基本…

【从零开始的LeetCode-算法】3222. 求出硬币游戏的赢家

给你两个 正 整数 x 和 y &#xff0c;分别表示价值为 75 和 10 的硬币的数目。 Alice 和 Bob 正在玩一个游戏。每一轮中&#xff0c;Alice 先进行操作&#xff0c;Bob 后操作。每次操作中&#xff0c;玩家需要拿出价值 总和 为 115 的硬币。如果一名玩家无法执行此操作&#…

MR30分布式IO模块与高效PLC协同

在现代工业自动化领域中&#xff0c;数据采集与控制系统扮演着至关重要的角色。其中&#xff0c;可编程逻辑控制器&#xff08;PLC&#xff09;和分布式IO模块&#xff08;Distributed I/O Modules&#xff09;是这一领域的两大核心组件。本文将详细介绍MR30分布式IO模块与PLC如…

贝尔不等式的验证

在量子计算机上运行一个实验&#xff0c;以演示使用Estimator原型违反CHSH不等式。 import numpy as npfrom qiskit import QuantumCircuit from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOpfrom qiskit_ibm_runtime import QiskitRuntim…

CSRF与SSRF

csrf(跨站请求伪造)的原理: csrf全称是跨站请求伪造(cross-site request forgery)&#xff0c;也被称为one-click attack 或者 session riding scrf攻击利用网站对于用户网页浏览器的信任&#xff0c;劫持用户当前已登录的web应用程序&#xff0c;去执行分用户本意的操作。 利…

Pr 视频效果:ASC CDL

视频效果/颜色校正/ASC CDL Color Correction/ASC CDL ASC CDL ASC CDL效果通过对红、绿、蓝三个原色通道的独立调整&#xff0c;实现对图像色彩的精确控制。在此基础上&#xff0c;还可用于调整处理后图像的整体饱和度。 ◆ ◆ ◆ 效果选项说明 斜率 Slope、偏移 Offset和功…