第 22 章 备忘录模式

1、游戏角色状态恢复问题

游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力), 当大战Boss后攻击力和防御力下降, 然后从备忘录对象恢复到大战前的状态

2、传统方案解决游戏角色恢复

类图

传统的方式的问题分析

  1. 一个对象,就对应一个保存对象状态的对象, 这样当我们游戏的对象很多时,不利于管理,开销也很大
  2. 传统的方式是简单地做备份, new 出另外一个对象出来,再把需要备份的数据放到这个新对象,但这就暴露了对象内部的细节
  3. 解决方案: ==> 备忘录模式

3、备忘录模式基本介绍

  1. 备忘录模式(Memento Pattern) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
  2. 可以这里理解备忘录模式:现实生活中的备忘录是用来记录某些要去做的事情,或者是记录已经达成的共同意见的事情,以防忘记了。
  3. 而在软件层面,备忘录模式有着相同的含义,备忘录对象主要用来记录一个对象的某种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作
  4. 备忘录模式属于行为型模式

4、备忘录模式原理类图

类图

  1. Originator :对象(需要保存状态的对象)
  2. Memento :备忘录对象,负责保存好记录, 即 Originator 内部状态
  3. Caretaker:守护者对象,负责保存多个备忘录对象, 使用集合管理, 提高效率
  4. 说明:如果希望保存多个 Originator 对象的不同时间的状态,只需要使用 HashMap <String, Collection> 存储即可,StringOriginator 对象的唯一标识(key),CollectionOriginator 对象不同时间的备忘录集合

代码实现

  1. Originator:实体类,该类的实例为需要保存状态的对象,saveStateMemento() 方法用于返回一个备忘录对象,getStateFromMemento() 方法用于从备忘录

    public class Originator {private String state;// 状态信息public String getState() {return state;}public void setState(String state) {this.state = state;}// 编写一个方法,可以保存一个状态对象 Memento// 因此编写一个方法,返回 Mementopublic Memento saveStateMemento() {return new Memento(state);}// 通过备忘录对象,恢复状态public void getStateFromMemento(Memento memento) {state = memento.getState();}
    }
    
  2. Memento:备忘录对象,负责保存对象的状态

    public class Memento {private String state;// 构造器public Memento(String state) {this.state = state;}public String getState() {return state;}}
    
  3. Caretker:聚合了备忘录的集合,即 List<Memento>

    public class Caretaker {// 在List 集合中会有很多的备忘录对象private List<Memento> mementoList = new ArrayList<Memento>();public void add(Memento memento) {mementoList.add(memento);}// 获取到第index个Originator 的 备忘录对象(即保存状态)public Memento get(int index) {return mementoList.get(index);}}
    
  4. Client:测试代码

    public class Client {public static void main(String[] args) {Originator originator = new Originator();Caretaker caretaker = new Caretaker();originator.setState(" 状态#1 攻击力 100 "); // 设置攻击速度caretaker.add(originator.saveStateMemento()); // 保存了当前的状态originator.setState(" 状态#2 攻击力 80 "); // 设置攻击速度caretaker.add(originator.saveStateMemento()); // 保存了当前的状态originator.setState(" 状态#3 攻击力 50 "); // 设置攻击速度caretaker.add(originator.saveStateMemento()); // 保存了当前的状态System.out.println("当前的状态是 =" + originator.getState());// 希望得到状态 1, 将 originator 恢复到状态1originator.getStateFromMemento(caretaker.get(0)); // 恢复对象属性System.out.println("恢复到状态1 , 当前的状态是");System.out.println("当前的状态是 =" + originator.getState());}}
    

5、备忘录模式解决游戏角色恢复

应用实例

游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力), 当大战Boss后攻击力和防御力下降, 然后从备忘录对象恢复到大战前的状态


类图


代码实现

  1. GameRole:游戏角色对应的实体类,createMemento() 方法用于创建备忘录对象,recoverGameRoleFromMemento() 用于从备忘录对象中恢复角色的状态

    public class GameRole {private int vit;private int def;// 创建Memento ,即根据当前的状态得到Mementopublic Memento createMemento() {return new Memento(vit, def);}// 从备忘录对象,恢复GameRole的状态public void recoverGameRoleFromMemento(Memento memento) {this.vit = memento.getVit();this.def = memento.getDef();}// 显示当前游戏角色的状态public void display() {System.out.println("游戏角色当前的攻击力:" + this.vit + " 防御力: " + this.def);}public int getVit() {return vit;}public void setVit(int vit) {this.vit = vit;}public int getDef() {return def;}public void setDef(int def) {this.def = def;}}
    
  2. Memento:备忘录对象

    public class Memento {// 攻击力private int vit;// 防御力private int def;public Memento(int vit, int def) {this.vit = vit;this.def = def;}public int getVit() {return vit;}public void setVit(int vit) {this.vit = vit;}public int getDef() {return def;}public void setDef(int def) {this.def = def;}}
    
  3. Caretaker:守护者对象,用于管理备忘录对象

    //守护者对象, 保存游戏角色的状态
    public class Caretaker {// 如果只保存一次状态private Memento memento;// 对GameRole 保存多次状态// private ArrayList<Memento> mementos;// 对多个游戏角色保存多个状态// private HashMap<String, ArrayList<Memento>> rolesMementos;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}
    
  4. Client:测试代码

    public class Client {public static void main(String[] args) {// 创建游戏角色GameRole gameRole = new GameRole();gameRole.setVit(100);gameRole.setDef(100);System.out.println("和boss大战前的状态");gameRole.display();// 把当前状态保存caretakerCaretaker caretaker = new Caretaker();caretaker.setMemento(gameRole.createMemento());System.out.println("和boss大战~~~");gameRole.setDef(30);gameRole.setVit(30);gameRole.display();System.out.println("大战后,使用备忘录对象恢复元气");gameRole.recoverGameRoleFromMemento(caretaker.getMemento());System.out.println("恢复后的状态");gameRole.display();}}
    

6、备忘录模式的注意事项和细节

  1. 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态
  2. 实现了信息的封装,使得用户不需要关心状态的保存细节
  3. 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存,这个需要注意
  4. 为了节约内存,备忘录模式可以和原型模式配合使用

适用的应用场景:

  1. 后悔药
  2. 打游戏时的存档
  3. Windows 里的 Ctrl + Z
  4. IE 中的后退
  5. 数据库的事务管理

第 22 章 备忘录模式相关推荐

  1. java实现备忘录模式_设计模式之第17章-备忘录模式(Java实现)

    设计模式之第17章-备忘录模式(Java实现) 好男人就是我,我就是曾小贤.最近陈赫和张子萱事件闹得那是一个沸沸扬扬.想想曾经每年都有爱情公寓陪伴的我现如今过年没有了爱情公寓总是感觉缺少点什么.不知道 ...

  2. Java设计模式(九)—中介者模式、备忘录模式、解释器模式

    本章目录标题 第21章 中介者模式 21.1 应用场景:智能家居 21.2 传统方式 21.3 中介者模式 21.4 应用案例:智能家居 21.5 中介者模式的注意事项 第22章 备忘录模式 22.1 ...

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

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

  4. 设计模式之备忘录模式(Memento)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  5. 设计模式(行为型模式)——备忘录模式(Memento)

    2019独角兽企业重金招聘Python工程师标准>>> 本章讲讲第三类和第四类. 备忘录模式(Memento) 主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫 ...

  6. 第19章 解释器模式(Interpreter Pattern)

    原文 第19章 解释器模式(Interpreter Pattern) 解释器模式 导读:解释器模式,平常用的比较的少,所以在写这个模式之前在博客园搜索了一番,看完之后那叫一个头大.篇幅很长,我鼓足了劲 ...

  7. php在线备忘录,备忘录模式(Memento)

    namespace DesignPatterns\Behavioral\Memento\Tests; use DesignPatterns\Behavioral\Memento\Caretaker; ...

  8. 备忘录模式(Memento)

    一.备忘录模式介绍 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 例如: 1.office重新打开时的恢复功能. ...

  9. 温故知新(8)——备忘录模式

    概述 先从面向对象的三大特征之一封装说起.面向对象的封装简单点说就是把状态(数据)和行为(操作这些数据的方法)放到一起,构成一个单元,通常叫做类.一个对象的行为是事先确定好的(静态)一些脚本,如果对象 ...

最新文章

  1. SpringBoot集成FreeMarker
  2. The Interface name: -- index:21 you checked seems not up.
  3. iOS高级面试之NSNotificationCenter是同步操作还是异步操作
  4. python 多图一窗口 打乱列表排序
  5. 爱是相互的,这样才是平衡
  6. 作者:朱怀球(1970-),男,北京大学教授。
  7. [转帖]jQuery框架学习第八天:ASP.NET jQuery实施方案
  8. 电子城西区北扩规划一路道路工程_雁塔区电子城街道重点项目进度
  9. 【snmp】测试流程
  10. jquery 时间相减获取天数_JQuery Datepicker实现JavaScript日期相减的小例子
  11. win7休眠设置在哪里_win7电脑不休眠怎么设置
  12. 多View统一Camera v1.2
  13. 国科大计算机算法与分析——陈玉福 马菲菲
  14. 漫画|前端江湖恩仇录始末
  15. 开发板 集成下载器 jtag_迅为i.MX6ULL开发板原理图分析介绍
  16. 【定制开发】【M3】基于Python+pygame实现的人机AI对战五子棋游戏(保姆级入门讲解)
  17. VR全景航拍:初学者如何做好全景航拍?
  18. 蓝色至深蓝色固体CY5.5琥珀酰亚胺脂Cyanine5.5 NHS ester,Cyanine5.5 SE,CY5.5 NHS,1469277-96-0
  19. 万能和弦与和弦走向浅析
  20. 公网访问本地内网web服务器【内网穿透】

热门文章

  1. Jetty 和tomcat 比较研究初探
  2. 图灵奖公布 | 高性能计算先驱、为超算铺平道路的Jack Dongarra获奖
  3. “过早的性能优化是魔鬼”
  4. 2020年入门数据分析选择Python还是SQL?七个常用操作对比!
  5. 2020 年微服务领域开源数字化报告发布,阿里扛起微服务大旗
  6. Serverless 如何做到快速发布?微应用平台技术实践
  7. 部分美团用户被取消支付宝支付;腾讯成全球市值最高社交媒体公司;微软首次公布GitHub产品路线图 | 极客头条
  8. 数据集永久下架,微软不是第一个,MIT 也不是最后一个
  9. 产业区块链:新基建中的底层技术基座,各行业资深人士应积极参与建设
  10. 为什么说 C++ 太复杂?有必要这么复杂吗?| 原力计划