设计模式之备忘录模式(下)

ops/2024/9/23 9:28:26/
3)实现多次撤销
1.结构图

在这里插入图片描述

对负责人类MementoCaretaker进行了修改,在其中定义了一个ArrayList类型的集合对象来存储多个备忘录。

2.代码实现
import java.util.*;public class MementoCaretaker {//定义一个集合来存储多个备忘录private ArrayList mementolist = new ArrayList();public ChessmanMemento getMemento(int i) {return (ChessmanMemento)mementolist.get(i);}public void setMemento(ChessmanMemento memento) {mementolist.add(memento);}
}

客户端类

public class Client {private static int index = -1; //定义一个索引来记录当前状态所在位置private static MementoCaretaker mc = new MementoCaretaker();public static void main(String args[]) {Chessman chess = new Chessman("车",1,1);play(chess);		chess.setY(4);play(chess);chess.setX(5);play(chess);	undo(chess,index);undo(chess,index);	redo(chess,index);redo(chess,index);}//下棋public static void play(Chessman chess) {//保存备忘录mc.setMemento(chess.save()); index++; System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "列。");}//悔棋public static void undo(Chessman chess,int i) {System.out.println("******悔棋******");index--; chess.restore(mc.getMemento(i-1)); //撤销到上一个备忘录System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "列。");}//撤销悔棋public static void redo(Chessman chess,int i) {System.out.println("******撤销悔棋******");	index ++; chess.restore(mc.getMemento(i+1)); //恢复到下一个备忘录System.out.println("棋子" + chess.getLabel() + "当前位置为:" + "第" + chess.getX() + "行" + "第" + chess.getY() + "列。");}
} 
3.注意

本实例只能实现最简单的Undo和Redo操作,并未考虑对象状态在操作过程中出现分支的情况。

如果在撤销到某个历史状态之后,用户再修改对象状态,此后执行Undo操作时可能会发生对象状态错误,在实际开发中,可以使用链表或者堆栈来处理有分支的对象状态改变。

4)总结

备忘录是一个很特殊的对象,只有原发器对它拥有控制的权力,负责人只负责管理,而其他类无法访问到备忘录。

1.优点
  • 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤。

  • 备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

2.缺点

资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。

3.适用场景
  • 保存一个对象在某一个时刻的全部状态或部分状态,以后需要时能够恢复到先前的状态,实现撤销操作。

  • 防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象。


http://www.ppmy.cn/ops/2434.html

相关文章

关于java数据样品以及转换

关于集合 List<String> List<String> list duoMapper.selectName(); [ "alice1", "alice2", "alice3", "alice4", "alice5", "alice6", "alice7", "alice8",…

Discourse API 调用数据返回的问题

在我们调用 Discourse API 创建一个主题的时候&#xff0c;我们会从 Discourse API 的调用文档中看到返回的 thumbnails 返回为 String。 但实际上 thumbnails 的返回在目前已经是一个对象了。 根据实际返回的结果&#xff0c;这个字段已经被设置成了一个 List。 真实的服务器…

【原创教程】EPLAN电气图纸设计规范

EPLAN电气图纸中的通用说明&#xff0c;说白了就是电气图纸的图纸概述、制图规范&#xff08;这里的规范根据每个公司及客户的要求不同进行更改&#xff09;。下面就以我们公司的规范要求&#xff0c;以实际的项目案例来对照讲述一下&#xff0c;通用说明的制作。 1.首先新建页…

界面控件DevExpress WinForms/WPF v23.2 - 富文本编辑器支持内容控件

众所周知内容控件是交互式UI元素(文本字段、下拉列表、日期选择器)&#xff0c;用于在屏幕上输入和管理信息。内容控件通常在模板/表单中使用&#xff0c;以标准化文档格式和简化数据输入。DevExpress文字处理产品库&#xff08;Word Processing Document API、WinForm和WPF富文…

详解App Inventor 2 中的文件作用域(作用范围):App、程序包、缓存、兼容、私有、共享

本文内容来自中文网文档“文件管理器”组件部分&#xff0c;详细介绍了每一种文件作用域的特点及用法。 下面是每种作用域类型的简述&#xff1a; App [推荐] &#xff1a;Android 2.2及更高版本上文件将从应用程序特定存储中读取和写入&#xff0c;在 Android 早期版本上&…

ChatGPT助力:写作步步高

ChatGPT无限次数:点击直达 html ChatGPT助力&#xff1a;写作步步高 引言 在当今信息爆炸的时代&#xff0c;写作作为一种重要的表达方式&#xff0c;扮演着不可或缺的角色。然而&#xff0c;随之而来的挑战是如何保持高质量的创作并不断提升写作水平。本文将探讨如何借助…

java项目连接sqlserver时报ssl相关错误,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

前端vue: 使用ElementUI适配国际化

i18n介绍 i18n&#xff08;其来源是英文单词 internationalization的首末字符i和n&#xff0c;18为中间的字符数&#xff09;是“国际化”的简称。 前端国际化步骤 1、安装i18n插件 安装插件时候&#xff0c;注意必须指定版本号&#xff0c;不然安装会报错。 npm i vue-i1…