备忘录模式简述

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

核心:保存某个对象的内部状态的拷贝,便于将对象恢复到原先的某个状态。

结构:

  • Originator: 原发器,决定Memento存储Originator的哪些内部状态。保存状态时负责创建一个备忘录,还原的时候利用一个备忘录进行恢复。
  • Memento: 备忘录,用于存储Originator的内部状态,也就是要被恢复的对象的状态,并且可以防止Originator以外的对象非法访问Memento。
  • Caretaker: 负责人,负责保存好备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。当备忘录份数过多时,根据需要使用相关容器进行组织(list、stack),当程序结束的时候,根据需要是否要先进行序列化和持久化。

关键代码:客户不与备忘录类耦合,与备忘录管理类耦合。

优点:

  • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
  • 实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点:

  • 消耗资源,如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

注意事项:

  • 为了符合迪米特原则(最少知道原则),还要增加一个管理备忘录的类。
  • 为了节约内存,可使用原型模式+备忘录模式。

开发中的场景:

  • 数据库软件中,事务操作的回滚操作。
  • ps中的历史记录。
  • office中的还原,撤销功能。
  • 棋类设计中的悔棋操作。
  • 打游戏时的存档。

实现

备忘录模式使用三个类 MementoOriginator 和 CareTaker,加上一个Client客户端测试类。

步骤1:创建源发器,这里的备忘操作和恢复操作与备忘录有关,可等到备忘录建好后在写,或者把这些操作放入备忘录类中

package com.ly.memento;/*** liyang 2020-08-26* 源发器,实际操作中的类,里面会创建一个备忘录对象,用于保存源发器的状态,在合适的时候需要时进行状态还原* 这里源发器实际存储的是一个学生信息,存储学生状态的类* 这里简化了类存储的信息,只有姓名和专业,仅作为说明备忘录模式*/public class Originator {String name;String major;//进行备忘操作,并返回备忘录对象public Memento memoOperation() {return new Memento(this);}//数据恢复,恢复成指定备忘录的值public void recoverOperation(Memento memento) {this.name = memento.getName();this.major = memento.getMajor();}public Originator(String name, String major) {this.name = name;this.major = major;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getMajor() {return major;}public void setMajor(String major) {this.major = major;}
}

步骤2:创建备忘录,明确要保存源发器中那些变量

package com.ly.memento;/*** liyang 2020-08-26* 备忘录类* 保存源发器类中相关信息的状态* 成员变量是源发器中需要备忘的,且设置为私有,防止非正常访问*/public class Memento {private String name;private String major;public Memento(Originator originator) {this.name = originator.name;this.major = originator.major;}public String getName() {return name;}public String getMajor() {return major;}
}

步骤3:创建备忘录的负责人

package com.ly.memento;import java.util.Stack;/*** liyang 2020-08-26* 负责人类,因为备忘录可能不止一个,比如五分钟自己创建一个备忘录,我们需要一个统一管理的地方,* 便于在恢复的时候根据所需状态,从负责人这个地方拿所需恢复的备忘录* 如果一个项目或者工程,从头到尾只有一个备忘录,那么就没有创建负责人类的必要了** 这里使用*/public class CareTaker {//private Memento memento;private final Stack<Memento> mementoStack = new Stack<>();public void setMemento(Memento memento) {mementoStack.push(memento);}public Memento getMemento() {if(!mementoStack.empty()) return mementoStack.pop();return null;}}

步骤4:客户端测试

package com.ly.memento;/*** liyang 2020-08-26* 客户端测试*/public class Client {public static void main(String[] args) {//创建一个源发器Originator originator = new Originator("Alice", "Mechanical Engineering");//创建一个备忘录Memento memento = originator.memoOperation();//创建一个负责人CareTaker careTaker = new CareTaker();//把备忘录放到负责人那里careTaker.setMemento(memento);//更新源发器,源发器决定转专业System.out.println("最开始的专业:" + originator.major);originator.setMajor("Civil Engineering");System.out.println("第1次转专业后:" + originator.major);//存一下当前状态careTaker.setMemento(originator.memoOperation());//学习一周后,发现这个专业比先前专业还坑比,决定回退到原专业,先去负责人拿回备忘录careTaker.getMemento();           //最近一次备忘录不是需要的memento = careTaker.getMemento(); //需要第二次弹出的备忘录//专业恢复originator.recoverOperation(memento);System.out.println("恢复到第1次转专业前:" + originator.major);//源发器决定第二次转专业,并且获得批准originator.setMajor("Computer Science");System.out.println("第2次转专业后:" + originator.major);//存一下当前状态careTaker.setMemento(originator.memoOperation());//新的学期开学,模拟专业信息丢失System.out.println("--模拟未知错误,导致专业信息丢失--");originator.setMajor("unknown error");System.out.println("当前专业:" + originator.major);//专业信息恢复originator.recoverOperation(careTaker.getMemento());System.out.println("-----专业信息恢复-----");System.out.println("当前专业:" + originator.major);System.out.println(originator.major.equals("Computer Science") ? "-----信息恢复成功-----": "-----信息恢复失败-----");}}

结果

最开始的专业:Mechanical Engineering
第1次转专业后:Civil Engineering
恢复到第1次转专业前:Mechanical Engineering
第2次转专业后:Computer Science
--模拟未知错误,导致专业信息丢失--
当前专业:unknown error
-----专业信息恢复-----
当前专业:Computer Science
-----信息恢复成功-----Process finished with exit code 0

参考资料:

https://www.runoob.com/design-pattern/memento-pattern.html

备忘录模式的Java实现相关推荐

  1. 设计模式-备忘录模式(Memento)-Java

    设计模式-备忘录模式(Memento)-Java 目录 文章目录 1.前言 2.示例案例-可悔棋的中国象棋 3.备忘录模式概述 3.1.备忘录模式定义 3.2.备忘录模式结构 3.3.备忘录模式结构图 ...

  2. 设计模式之备忘录模式(Java实现)

    Memento(备忘录) 一.意图 在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态.这样以后就可以将对象恢复到原先保存的状态. 二.结构 此模式的结构图如图7-43所示. 其中 ...

  3. Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)

    Java设计模式Ⅶ 1.备忘录模式 1.1 备忘录模式概述 1.2 代码理解 2.解释器模式 2.1 解释器模式概述 3.状态模式 3.1 状态模式概述 3.2 代码理解 4.策略模式 4.1 策略模 ...

  4. java备忘录模式 类图,折腾Java设计模式之备忘录模式

    备忘录模式 Without violating encapsulation, capture and externalize an object's internal state allowing t ...

  5. 设计模式:备忘录模式(Memento)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  6. java备忘录模式应用场景_图解Java设计模式之备忘录模式

    图解Java设计模式之备忘录模式 游戏角色状态恢复问题 游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态. ...

  7. 《JAVA与模式》之备忘录模式

    备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一 ...

  8. java设计模式---备忘录模式

    一.引子 俗话说:世上难买后悔药.所以凡事讲究个"三思而后行",但总常见有人做"痛心疾首"状:当初我要是--.如果真的有<大话西游>中能时光倒流的& ...

  9. Java设计模式之行为型:备忘录模式

    在开发过程中,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态.比如,在编程时假如编写失误,例如不小心误删除了几行代码,我们希望返回删除前的状态,便可以使用 Ctrl+Z 来进行返回,这时 ...

最新文章

  1. 本地Windows远程桌面连接阿里云Ubuntu服务器
  2. informix 访问mysql_informix用户权限的介绍及查看方法
  3. 6.MySQL图形化工具的使用
  4. 栈和队列之仅用递归函数和栈操作逆序一个栈
  5. 【OpenCV 例程200篇】83. 频率域低通滤波:印刷文本字符修复
  6. 给apm换一个软件源
  7. java类包装器有什么用_Java中的包装器类
  8. php larval开发规范,Laravel 开发规范摘要
  9. 网站竞价推广抗恶意点击及屏蔽特定地区IP实例
  10. 【Axure高保真原型】拖拉拽元件库
  11. 免费APP内测分发托管平台,支持应用合并、内测分发、扫码下载,下载量安装量统计,版本记录和应用在线封装打包app
  12. java中考勤管理_JAVA人事员工考勤管理(含论文)源码
  13. 2022年全球及中国天然橡胶产业供需趋势及行业期货市场走势:预计供需双增长,价格上行[图]
  14. yii2.0 中文手册 php,Yii2.0 高级版开发指南
  15. Altium Designer多图纸原理图关联设计方法
  16. 平板win10 android哪个耗电,Win10充分利用设置提升平板/笔记本电池续航方法
  17. javaweb基于SSH开发健康档案管理系统+论文+开题报告 课程设计 大作业源码 毕业设计
  18. 安卓dtmf识别_安卓dtmf识别_基于Python的DTMF信号识别
  19. Python自学日记28——如何选择学习资料
  20. 因变量是连续变量spss里面用什么模型做回归

热门文章

  1. Android基于高德地图实现多人实时共享位置
  2. Type interface com.mybatis.mapper.UserMapper is not known to the MapperRegistry
  3. Hive stage划分
  4. CentOS8配置MySQL双主互备(安装centos8及MySQL)
  5. [最小割]狼和羊的故事
  6. C语言编程学生成绩管理系统
  7. 【基础知识】rubymine常用快捷键
  8. HTML + CSS + JS 轮番图
  9. MPB:上海交大肖湘组-​海洋微生物的厌氧高压培养实验
  10. QDialog概率卡死问题