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

一、什么是备忘录模式:

备忘录模式提供了一种恢复状态的机制,在不破坏封装的前提下,捕获对象的内部状态,并保存在该对象之外,保证该对象能够恢复到某个历史状态;备忘录模式将保存的细节封装在备忘录中,除了创建它的创建者之外其他对象都不能访问它,并且实现了即使要改变保存的细节也不影响客户端。但是备忘录模式都是多状态和多备份的,会早用较多的内存,消耗资源。

二、UML结构图:

  • Originator:原发器,负责创建一个备忘录,用于记录当前对象的内部状态,也可以使用它来利用备忘录恢复内部状态,同时原发器还可以根据需要决定 Memento 存储 Originator 的哪些内部状态。
  • Memento:备忘录,用于存储 Originator 的内部状态,并且可以防止 Originator 以外的对象访问Memento。在备忘录 Memento 中有两个接口,其中 Caretaker 只能看到备忘录中的窄接口,它只能将备忘录传递给其他对象。Originator可以看到宽接口,允许它访问返回到先前状态的所有数据。
  • Caretaker: 负责人,对备忘录 Memento 进行管理,保存和提供备忘录,但不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。

备忘录模式的核心就是备忘录 Memento,在备忘录中存储的就是原发器 Originator 的部分或者所有的状态信息,而这些状态信息是不能够被其他对象所访问的,也就是说我们是不能使用备忘录之外的对象来存储这些状态信息,如果暴漏了内部状态信息就违反了封装的原则,故备忘录除了原发器外其他对象都不可以访问。所以为了实现备忘录模式的封装,我们需要对备忘录的访问做些控制:

(1)对原发器:可以访问备忘录里的所有信息。

(2)对负责人:不可以访问备忘录里面的数据,但是他可以保存备忘录并且可以将备忘录传递给其他对象。

(3)其他对象:不可访问也不可以保存,它只负责接收从负责人那里传递过来的备忘录同时恢复原发器的状态。

所以备忘录模式最理想的情况就是只允许生成该备忘录的那个原发器访问备忘录的内部状态,典型的备忘录代码如下:

class Memento {private String state;public Memento(Originator o){state = o.state;}public void setState(String state){this.state=state;}public String getState(){return this.state;}  
}

三、代码实现:

我们以游戏挑战BOSS为实现场景:在挑战BOSS之前,角色的血量、蓝量都是满值,然后存档,在大战BOSS时,由于操作失误导致血量和蓝量大量损耗,所以只好恢复到刚刚开始的存档点,继续进行大战BOSS了。

UML结构图如下:

首先是游戏角色类:Role.java

public class Role{    private int bloodFlow;private int magicPoint;public Role(int bloodFlow,int magicPoint){this.bloodFlow = bloodFlow;this.magicPoint = magicPoint;}public int getBloodFlow() {return bloodFlow;}public void setBloodFlow(int bloodFlow) {this.bloodFlow = bloodFlow;}public int getMagicPoint() {return magicPoint;}public void setMagicPoint(int magicPoint) {this.magicPoint = magicPoint;}/*** @desc 展示角色当前状态*/public void display(){System.out.println("用户当前状态:");System.out.println("血量:" + getBloodFlow() + ";蓝量:" + getMagicPoint());}/*** @desc 保持存档、当前状态*/public Memento saveMemento(){return new Memento(getBloodFlow(), getMagicPoint());}/*** @desc 恢复存档*/public void restoreMemento(Memento memento){this.bloodFlow = memento.getBloodFlow();this.magicPoint = memento.getMagicPoint();}
}

备忘录:Memento.java

class Memento {private int bloodFlow;private int magicPoint;public int getBloodFlow() {return bloodFlow;}public void setBloodFlow(int bloodFlow) {this.bloodFlow = bloodFlow;}public int getMagicPoint() {return magicPoint;}public void setMagicPoint(int magicPoint) {this.magicPoint = magicPoint;}public Memento(int bloodFlow,int magicPoint){this.bloodFlow = bloodFlow;this.magicPoint = magicPoint;}
}

负责人:Caretaker.java

public class Caretaker {Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}
}

客户端:Client.java

public class Client {public static void main(String[] args) {//打BOSS之前:血、蓝全部满值Role role = new Role(100, 100);System.out.println("----------大战BOSS之前----------");role.display();//保持进度Caretaker caretaker = new Caretaker();caretaker.memento = role.saveMemento();//大战BOSS,快come Over了role.setBloodFlow(20);role.setMagicPoint(20);System.out.println("----------大战BOSS----------");role.display();//恢复存档role.restoreMemento(caretaker.getMemento());System.out.println("----------恢复----------");role.display();}
}

运行结果:

四、备忘录模式小结:

1、优点:

(1)实现了信息的封装,用户不需要关心状态的保存细节,窄接口保证了只有发起者才能访问备忘录对象的状态;

(2)简化了原发器,把备忘录对象保存到原发器对象之外,这样原发器角色就不需要对各个备份的状态进行管理。

2、缺点:

在实际应用中,备忘录模式都是多状态和多备份的,每保存一次对象状态都需要消耗一定的系统资源,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的内存存储空间,消耗资源。

3、适用场景:

(1)如果有需要提供回滚操作的需求,使用备忘录模式非常适合,比如jdbc的事务操作,文本编辑器的Ctrl+Z恢复等。

(2)保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时它能够恢复到先前的状态,实现撤销操作。防止外界对象破坏一个对象历史状态的封装性。


设计模式系列文章:

Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)

Java设计模式之创建型:建造者模式

Java设计模式之创建型:单例模式

Java设计模式之创建型:原型模式

Java设计模式之结构型:适配器模式

Java设计模式之结构型:装饰器模式

Java设计模式之结构型:代理模式

Java设计模式之结构型:桥接模式

Java设计模式之结构型:外观模式

Java设计模式之结构型:组合模式

Java设计模式之结构型:享元模式

Java设计模式之行为型:策略模式

Java设计模式之行为型:模板方法模式

Java设计模式之行为型:责任链模式

Java设计模式之行为型:观察者模式

Java设计模式之行为型:访问者模式

Java设计模式之行为型:中介者模式

Java设计模式之行为型:命令模式

Java设计模式之行为型:状态模式

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

Java设计模式之行为型:迭代器模式

Java设计模式之行为型:解释器模式


原博客地址:设计模式读书笔记-----备忘录模式_chenssy 的技术博客-CSDN博客

Java设计模式之行为型:备忘录模式相关推荐

  1. JAVA设计模式(14) —行为型模板方法模式(Template Method)

    1 定义: 模板方法模式(Template Method) Define the skeleton of an algorithm in anoperation, deferring some ste ...

  2. Java设计模式之创建型-建造者模式 (Builder)

  3. Java设计模式(16)中介模式(Mediator模式)

    Mediator定义:用一个中介对象来封装一系列关于对象交互行为. 为何使用Mediator模式/中介模式 各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉 ...

  4. Java设计模式(1)工厂模式(Factory模式)

    工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...

  5. Java设计模式(8)组合模式(Composite模式)

    Composite定义:将对象以树形结构组织起来,以达成"部分-整体" 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Compo ...

  6. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

  7. Java设计模式之行为型:解释器模式

    一.什么是解释器模式:         解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例. 这里我们将语言理解成使用规定格式和语 ...

  8. Java设计模式之行为型:访问者模式

    背景: 去医院看病时,医生会给你一个处方单要你去拿药,拿药我们可以分为两步走: (1)去柜台交钱,划价人员会根据处方单上的药进行划价,交钱. (2)去药房拿药,药房工作者同样根据处方单给你相对应的药. ...

  9. Java设计模式之行为型:状态模式

    背景: 介绍状态模式前,我们先看这样一个实例:公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上.下图是他们系统的主要工作: 当第一眼看到这个系统时你就看出这是一个状态图,每个框都代表 ...

最新文章

  1. Learn OpenGL (十):材质
  2. 你是如何自学 Python 的?
  3. hdu4990 矩阵快速幂
  4. 泥浆配制_朝政泥浆——广西田阳县百东河水库溢洪道穿越钻泥浆配制简述(3)...
  5. GET与POST可传递的最大值到底是多少?
  6. 考研生的努力程度是有多恐怖!
  7. 直博5年!叹我年少轻狂!头4年一篇1作SCI也没有...
  8. SpringBoot指南(三)——静态资源、欢迎页、Favicon、默认页面
  9. 不同语言Sql Server的库交换出现乱码
  10. NetBeans 6.9 正式版发布!
  11. matlab 马丢函数,振幅调制产生马丢光束的方法与流程
  12. HTML5-Geolocation(地理定位功能)
  13. 【机械仿真】基于matlab GUI机械臂运动控制【含Matlab源码 063期】
  14. 开源,想说爱你不容易
  15. mysql输入20万数据_mysql生成20万条数据(连表插入)
  16. java 生成word 分页,jsp转word + 分页
  17. 服务器的回收站在哪个文件夹,Windows系统回收站的文件保存在哪个磁盘上
  18. 【408】计算机组成原理第一轮强化笔记
  19. SQL-Server 零基础入门教程[下]
  20. 魔兽争霸兽族打疯狂不死

热门文章

  1. 三十九、SPSS神器界面功能介绍,计算变量和个案计数和加权
  2. 八、马科维茨投资组合
  3. Python与常见加密方式
  4. 极客产品经理学习笔记
  5. 生物岛实验室闵明玮课题组诚聘副研究员/博士后/科研助理/实习生
  6. WWW 2021有哪些值得读的图机器学习相关论文?
  7. 直播 | 旷视研究院最新理论成果:批归一化和权重衰减的球面优化机制
  8. 实战分享之专业领域词汇无监督挖掘
  9. java: -source 1.5 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符)
  10. mysql有imp命令吗_快速MySQL Imp