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

适用场景:

1、保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态;
2、对一个提供对象提供可回滚(rollback)的操作。

通用类图:

对于备忘录,大家都很熟悉了,就是保存一份对象副本,在需要的时候再取出来回复为原来的状态。关于回滚(rollback),我们也在关系数据库中的事务机制中有所学习了。

上面的类图中,Originator 类是需要被保存的角色,它应该具有自己的内部状态、属性和数据等;而 Memento 类则是用于保存某一时刻下 Originator 副本的角色;Caretaker 类则是一个备忘录管理角色,Memento 类恢复一个自身的副本时应该通过 Caretaker 来实现。

按照类图用代码实现一下:

// 原始对象角色
class Originator {private String state;public Originator(String state) {this.setState(state);}public String getState() {return this.state;}public void setState(String state) {this.state = state;}// 创建备忘录,并备份当前状态public Memento createMemento() {return new Memento(this.state);}// 恢复备忘录中的备份状态public void rollbackState(Memento memento) {this.setState(memento.getState());}
}
// 备忘录角色
class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return this.state;}public void setState(String state) {this.state = state;}
}
// 备忘录管理者角色
class Caretaker {private Memento memento;public Memento getMemento() {return this.memento;}public void setMemento(Memento memento) {this.memento = memento;}
}
// 测试类
public class Client {public static void main(String[] args) {Originator originator = new Originator("原来的状态 ...");System.out.println(originator.getState());// 创建备份管理者并进行备份Caretaker caretaker = new Caretaker();caretaker.setMemento(originator.createMemento());originator.setState("修改后的状态 ...");System.out.println(originator.getState());// 恢复状态originator.rollbackState(caretaker.getMemento());System.out.println(originator.getState());}
}

测试结果:

原来的状态 ...
修改后的状态 ...
原来的状态 ...

看看上面的代码,觉得没什么特别,感觉不像是一个设计模式,原因是挺简单的。不过,在真正运用这 Memento 模式时,难度应该会相当大。对比一下关系数据库中的事务机制,要实现回滚(rollback),RDBMS 在后台做了多少用户不了解的工作,一个个记录点的正确选择、判断发生故障的监测机制以及正确地恢复到提交前的状态等等…这些,马上就加大了 Memento 模式的使用了。

基于 Java 中的 clone 技术,让 Originator 直接实现 Cloneable 接口,实现其其中的 clone() 方法,类图如下:

简单代码实现如下:

// 原始对象角色,其实是身兼多职,据所有功能于一身
class Originator implements Cloneable {// 保存备的份对象private Originator backup;private String state;public Originator(String state) {this.setState(state);}public String getState() {return this.state;}public void setState(String state) {this.state = state;}// 创建一个备份,即记录当前对象的拷贝public void createMemento() {this.backup = this.clone();}// 恢复一个备份,即获取backup的内部状态public void restoreMemento() {if(this.backup != null) {this.setState(this.backup.getState());}}/*** 覆盖 clone() 方法,如果需要深拷贝,* 就不能 这么简单地实现了,会复杂些*/@Overrideprotected Originator clone() {try {return (Originator)super.clone();}catch(CloneNotSupportedException e) {e.printStackTrace();}return null;}
}
// 测试类
public class Client {public static void main(String[] args) {Originator originator = new Originator("原来的状态 ...");System.out.println(originator.getState());// 进行备份originator.createMemento();originator.setState("修改后的状态 ...");System.out.println(originator.getState());// 恢复备份originator.restoreMemento();System.out.println(originator.getState());}
}


测试结果:
原来的状态 ...
修改后的状态 ...
原来的状态 ...

虽然上面第二种实现偏离了 Memento 模式的定义,即“在该对象之外保存这个状态”,现在无论是原来的对象还是备份后的对象,甚至备份管理者 Caretaker 类都是在 Originator 类中,程序结构虽然简单,但如果 Originator 类中有多个状态,而且有多个引用变量时,实现 clone() 方法似乎也没有那么简单,因为要考虑到深拷贝,这就与 Prototype 模式(原型模式)有个共同需要考虑的方面了。

此外,也可以运用 Java 中的对象序列化、反序列化机制来实现备份的功能,可以将一个对象的内部状态序列化称为二进制流,保存到文件或数据库中,需要时再反序列化回来。不过,对于 Java 中对象的序列化、反序列化要注意序列化版本的兼容性,具体请参考相关书籍。要使一个对象可以被序列化,需要让某个类实现 java.lang.Serializable 接口,它是一个标志性接口,里面一个方法也没有,只要在类声明时加上 implements Serializable 即可。

我的相关文章:

(Prototype)原型模式的Java实现http://haolloyin.blog.51cto.com/1177454/333442

转载于:https://blog.51cto.com/haolloyin/351000

备忘录模式(Memento)的原版与简化版实现相关推荐

  1. 二十四种设计模式:备忘录模式(Memento Pattern)

    备忘录模式(Memento Pattern) 介绍 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到保存的状态. 示例 有一个Message实体类 ...

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

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

  3. java memento_备忘录模式-Memento Pattern(Java实现)

    备忘录模式-Memento Pattern Memento备忘录设计模式是一个保存另外一个对象内部状态拷贝的对象,这样以后就可以将该对象恢复到以前保存的状态. 本文中的场景: 有一款游戏可以随时存档, ...

  4. 备忘录模式 Memento 快照模式 标记Token模式 行为型 设计模式(二十二)

    备忘录模式 Memento 沿着脚印,走过你来时的路,回到原点. 苦海翻起爱恨 在世间难逃避命运 相亲竟不可接近 或我应该相信是缘份 一首<一生所爱>触动了多少人的心弦,一段五百年都没有结 ...

  5. Java备忘录模式(Memento)

      本文我们来介绍下java23种设计模式中的备忘录模式. 备忘录模式Memento 使用场景 录入大批人员资料.正在录入当前人资料时,发现上一个人录错了, 此时需要恢复上一个人的资料,再进行修改. ...

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

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

  7. Net设计模式实例之备忘录模式(Memento Pattern)

    一.备忘录模式简介(Brief Introduction) 备忘录模式(Memento Pattern),在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以就该对 ...

  8. 『设计模式』备忘录模式(memento)下象棋,我就想悔棋怎么办

    23种设计模式+额外常用设计模式汇总 (持续更新) Memento模式的关键就是要在不破坏封装性的前提下,捕获一个对象的内部状态并在该对象之外保存这个状态.这样以后就可以利用该保存的状态实施恢复操作. ...

  9. 【设计模式】—— 备忘录模式Memento

    前言:[模式总览]----------by xingoo 模式意图 这个模式主要是想通过一个对象来记录对象的某种状态,这样有利于在其他需要的场合进行恢复. 该模式还有跟多可以扩展的地方,比如可以记录多 ...

  10. [设计模式-行为型]备忘录模式(Memento)

    一句话 让某个对象可以取到之前的某个状态值. 概括 解析 MEMENTO-同时跟几个MM聊天时,一定要记清楚刚才跟MM说了些什么话,不然MM发现了会不高兴的哦,幸亏我有个备忘录,刚才与哪个MM说了什么 ...

最新文章

  1. Numpy入门教程:练习作业01
  2. Android IOC模块,利用了Java反射和Java注解
  3. mkimage工具讲解
  4. Java里阻塞线程的三种实现方法
  5. 人工智能时代号角已吹响 COMPUTEX如何凝聚AI这股力量?
  6. leetcode252. 会议室
  7. 沉得住气的程序员们!
  8. 02--Activiti初始化表
  9. Typecho中的gravatar头像无法加载
  10. 微波遥感SNAP(四)——检测地表沉降(2)相位解缠与地理编码
  11. ECharts - dataset组件的用法详解
  12. 单片机破解的常用方法及应对策略
  13. 国外开放的硕博论文、期刊、数据库下载网站
  14. 纵享丝滑滑动切换的周月日历,水滴效果,可高度定制,仿小米日历
  15. 空间|时间|对象 圈人 + 目标人群透视 - 暨PostgreSQL 10与Greenplum的对比和选择
  16. [Neo4j] CQL命令
  17. 【Mac双系统设置系统默认启动系统】解决方案
  18. OpenWrt开发必备软件模块——系统总线ubus
  19. 艾永亮:时代的较量,谁在定义四个轮子的未来?
  20. Ubuntu18.04.4安装

热门文章

  1. ​DL_WITH_PY系统学习(第3章)
  2. 2017年10月31日结束Outlook 2007与Office 365的连接
  3. 如何动态修改windows下的host文件
  4. mysql select in 怎么优化
  5. 如何在Linux上从命令行嗅探HTTP流量
  6. Bitcoin.com宣布将成立2亿美元的BCH生态系统投资基金
  7. hbase 数据库简介安装与常用命令的使用
  8. 阿里云服务器ecs绑定域名,端口的问题,不用80端口
  9. GNU make manual 翻译(二十六)
  10. 轻量函数式 JavaScript:八、列表操作