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.rhkb.cn/news/465451.html

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

相关文章

国际版JAVA同城打车源码同城服务线下结账系统源码适配PAD支持Android+IOS+H5

一、数据中心 总用户数今日接单数量今日新增今日收入本月新增本月收入本年新增本年收入 二、用户中心 全部用户普通用户师傅用户推广员用户 三、财务中心 提现管理收入统计提现统计充值统计充值记录保证金管理平台收入统计 四、首页装修 轮播图分享图语音播报配置 五…

Ubuntu学习笔记 - Day3

文章目录 学习目标&#xff1a;学习内容&#xff1a;学习笔记&#xff1a;vim简介vim键盘图工作模式 vim移动光标操作上下左右移动翻页 vim替换和删除操作替换删除 vim插入模式详解进入模式搜索 vim底行模式操作保存退出行号 学习目标&#xff1a; 一周掌握 Linux基本使用技巧 …

数据结构 - 图

今天我们开始学习目前学习到的最难最复杂的数据结构图。 简单回顾一下之前学习的数据结构&#xff0c;数组、单链表、队列等线性表中数据元素是一对一关系&#xff0c;而树结构中数据元素是一对多关系&#xff0c;而图结构中数据元素则是多对多关系&#xff0c;任何两个数据元素…

java.lang.NoClassDefFoundError: kotlin/jvm/JvmInline

springboot项目&#xff0c;调用接口时&#xff0c;报这个错误&#xff0c;跟踪断点发现数据库也查询到了数据&#xff0c;就是在返回时报错了&#xff0c;后来一看是pom.xml中引入了 <dependency><groupId>com.fasterxml.jackson.module</groupId><artif…

WebAPI编程(第五天,第六天,第七天)

WebAPI编程&#xff08;第五天&#xff0c;第六天&#xff0c;第七天&#xff09; **day05 - Web APIs****1.1. **元素偏移量 offset 系列1.1.1 offset 概述1.1.2 offset 与 style 区别offsetstyle 1.1.3 案例&#xff1a;获取鼠标在盒子内的坐标1.1.4 案例&#xff1a;模态框拖…

xshell连接不上linux的原因

1、首先我们确定好linux的配置&#xff0c;右键选择设置&#xff0c;将网络适配器设置成NAT模式 2、点击linux编辑&#xff0c;选择虚拟网络 打开以后选中自己要配置的服务 3、进入以后选中自己的服务&#xff0c;确保是NAT模式&#xff0c;然后配置好子网ip&#xff08;尽量ip…

进程与线程+多线程优势

区别&#xff1a; 1、进程中包含线程&#xff0c;每一个进程都至少一个线程&#xff08;主线程&#xff09; 2、进程是申请系统资源的最小单位 3、进程是CPU调度的最小单位 4、线程之间共享进程申请的系统资源 5、一个线程崩溃了会影响整个进程 进程的组织方式&#xff1…

Unity3D学习FPS游戏(8)装弹和弹夹UI显示

前言&#xff1a;实现了武器的基本发射功能&#xff0c;但是我们弹夹数量是有限&#xff0c;之前并没有做装弹和弹夹显示的功能。本篇实现装弹和弹夹显示。 装弹和弹夹UI显示 装弹目标思路和实现 弹夹UI显示目标弹夹UI的思路和实现UI代码的思路和实现 武器控制的完整代码效果补…

计算机网络——网络层导论

转发是局部功能——数据平面 路由是全局的功能——控制平面 网卡 网卡&#xff0c;也称为网络适配器&#xff0c;是计算机硬件中的一种设备&#xff0c;主要负责在计算机和网络之间进行数据传输。 一、主要功能 1、数据传输&#xff1a; 发送数据时&#xff0c;网卡将计算机…

6款IntelliJ IDEA插件,让Spring和Java开发如虎添翼

文章目录 1、SonarLint2、JRebel for IntelliJ3、SwaggerHub插件4、Lombok插件5、RestfulTool插件6、 Json2Pojo插件7、结论 对于任何Spring Boot开发者来说&#xff0c;两个首要的目标是最大限度地提高工作效率和确保高质量代码。IntelliJ IDEA 是目前最广泛使用的集成开发环境…

【MySQL】深度学习与解析 : 库的操作知识整合

前言&#xff1a;本节内容是MySQL库的操作&#xff0c; 内容较少&#xff0c; 大体内容为创建库、删除库、修改库、库备份操作。 ps:本节内容适合安装了MySQL的友友们进行观看&#xff0c; 实操更有利于记住哦。 目录 创建数据库 查看数据库列表 创建数据库 删除数据库 …

开源 AI 智能名片 2+1 链动模式 S2B2C 商城小程序与私域流量圈层

摘要&#xff1a;本文探讨了私域流量圈层的特点以及其在当今时代的重要性&#xff0c;分析了开源 AI 智能名片 21 链动模式 S2B2C 商城小程序源码在私域流量圈层构建中的作用&#xff0c;阐述了产品在圈层时代被标签化的现象&#xff0c;并以实例展示了如何利用该小程序源码打造…

第11章 LAMP架构企业实战

Linux下LAMP(Linux+Apache+MySQL/MariaDB+Perl/PHP/Python)是一组用来搭建动态网站的开源软件架构,本身是各自独立的软件服务,放在一起使用,拥有了越来越高的兼容度,共同组成了一个强大的Web应用程序平台。 本章介绍互联网主流企业架构LAMP应用案例、PHP解释性语言详解、…

vscode php Launch built-in server and debug, PHP内置服务xdebug调试,自定义启动参数配置使用示例

在vscode中&#xff0c;当我们安装了插件 PHP Debug&#xff08;xdebug.php-debug&#xff09;或者 xdebug.php-pack 后 我们通过内置默认的 php xdebug配置启动php项目后&#xff0c;默认情况下我们在vscode中设置断点是不会生效的&#xff0c;因为我们的内置php服务默认启动时…

揭秘云计算 | 2、业务需求推动IT发展

揭秘云计算 | 1、云从哪里来&#xff1f;-CSDN博客https://blog.csdn.net/Ultipa/article/details/143430941?spm1001.2014.3001.5502 书接上文&#xff1a; 过去几十年间IT行业从大型主机过渡到客户端/服务器&#xff0c;再过渡到现如今的万物互联&#xff0c;IT可把控的资…

Golang | Leetcode Golang题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; func getSuccessor(node *TreeNode) *TreeNode {succ : node.Rightfor succ.Left ! nil && succ.Left ! node {succ succ.Left}return succ }func convertBST(root *TreeNode) *TreeNode {sum : 0node : rootfor node ! nil {if n…

达梦数据守护集群_动态增加实时备库

目录 1、概述 2、实验环境 2.1环境信息 2.2配置信息 2.3 查看初始化参数 3、动态增加实时备库 3.1数据准备 3.2配置新备库 3.3动态增加MAL配置 3.4 关闭守护进程及监视器 3.5修改归档&#xff08;方法1&#xff1a;动态添加归档配置&#xff09; 3.6 修改归档&…

思维导图工具有哪些?10款思维导图特色介绍

电脑的普及&#xff0c;互联网的便捷。使我们平时工作、学习等场景下&#xff0c;常常离不开思维导图的辅助。思维导图是可以让我们所需要介绍的知识点以图文形式结合&#xff0c;展示出来。帮助我们方便理解。因此&#xff0c;一款好的思维导图工具&#xff0c;能让我们制作的…

7.2 设计模式

设计模式 7.3.1 设计模式的要素7.3.2 创建型设计模式7.3.3 结构性设计模式1. Adapter (适配器)2. Bridge(桥接)3.Composite(组合)4.Decorator(装饰)5.Facade(外观)6.Flyweight(享元)7.Proxy(代理)8. 结构型模式比较 7.3.4 行为型设计模式1 Chain of Responsibility 责任链模式2…

【Wi-Fi】802.11ac wave1 vs 802.11ac wave2

参考链接 difference between 11ac wave1 and wave2 | 11ac-wave1 vs 11ac-wave2 什么是802.11ac和802.11ac Wave2 - 华为 Notes&#xff5c;802.11ac Wave1与Wave2 - 知乎 802.11ac-wave1 2013年&#xff0c;IEEE发布了802.11ac标准&#xff0c;在Wave2出来之后&#xf…