Java 设计模式系列(十八)备忘录模式(Memento)

备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

一、备忘录模式的结构

备忘录模式所涉及的角色有三个:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色。

  • 备忘录(Memento)角色

  (1)将发起人(Originator)对象的内战状态存储起来。备忘录可以根据发起人对象的判断来决定存储多少发起人(Originator)对象的内部状态。

  (2)备忘录可以保护其内容不被发起人(Originator)对象之外的任何对象所读取。

  备忘录有两个等效的接口:

* 窄接口:负责人(Caretaker)对象(和其他除发起人对象之外的任何对象)看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他的对象。

  * 宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。

  • 发起人(Originator)角色:

  (1)创建一个含有当前的内部状态的备忘录对象。

  (2)使用备忘录对象存储其内部状态。

  • 负责人(Caretaker)角色

  (1)负责保存备忘录对象。

  (2)不检查备忘录对象的内容。

源代码

(1) Memento 接口

/**
* 备忘录的窄接口,没有任何方法定义
*/
public interface Memento { }

(2) Originator

/**
* 原发器对象
*/
public class Originator implements Memento {
/**
* 示意,表示原发器的状态
*/
private String state = ""; /**
* 创建保存原发器对象的状态的备忘录对象
* @return 创建好的备忘录对象
*/
public Memento createMemento() {
return new MementoImpl(state);
} /**
* 重新设置原发器对象的状态,让其回到备忘录对象记录的状态
* @param memento 记录有原发器状态的备忘录对象
*/
public void retriveMemento(Memento memento) {
MementoImpl mementoImpl = (MementoImpl)memento;
this.state = mementoImpl.getState();
} /**
* 真正的备忘录对象,实现备忘录窄接口
* 实现成私有的内部类,不让外部访问
*/
private static class MementoImpl implements Memento{
/**
* 示意,表示需要保存的状态
*/
private String state = "";
public MementoImpl(String state){
this.state = state;
}
public String getState() {
return state;
}
}
}

(3) Caretaker

/**
* 负责保存备忘录的对象
*/
public class Caretaker {
/**
* 记录被保存的备忘录对象
*/
private Memento memento = null;
/**
* 保存备忘录对象
* @param memento 被保存的备忘录对象
*/
public void saveMemento(Memento memento){
this.memento = memento;
}
/**
* 获取被保存的备忘录对象
* @return 被保存的备忘录对象
*/
public Memento retriveMemento(){
return this.memento;
}
}

(4) 测试

public class Main {

    public static void main(String[] args) {

        Originator o = new Originator();
Caretaker c = new Caretaker();
//改变负责人对象的状态
o.setState("On");
//创建备忘录对象,并将发起人对象的状态储存起来
c.saveMemento(o.createMemento());
//修改发起人的状态
o.setState("Off");
//恢复发起人对象的状态
o.restoreMemento(c.retrieveMemento()); System.out.println(o.getState());
}
}

二、多备份点

(1) Memento

public interface Memento {
int getIndex();
}

(2) Originator

public class Originator implements Memento {

    //检查点指数
private int index; /** 示意,表示原发器的状态 */
private String state = ""; /** 创建保存原发器对象的状态的备忘录对象 */
public Memento createMemento() {
return new MementoImpl(state, index);
} /** 重新设置原发器对象的状态,让其回到备忘录对象记录的状态 */
public void restoreMemento(Memento memento) {
MementoImpl mementoImpl = (MementoImpl)memento;
this.state = mementoImpl.getState();
index = memento.getIndex();
} // Ingore getter/setter /**
* 真正的备忘录对象,实现备忘录窄接口
* 实现成私有的内部类,不让外部访问
*/
private static class MementoImpl implements Memento {
private int index; /** 示意,表示需要保存的状态*/
private String state = "";
public MementoImpl(String state, int index){
this.state = state;
this.index = index;
} // Ingore getter/setter
}
}

(3) Caretaker

public class Caretaker {
/** 记录被保存的备忘录对象 */
private List<Memento> mementos = new ArrayList<>();
private int current; /** 保存备忘录对象 */
public int saveMemento(Memento memento){
this.mementos.add(memento);
return current++;
} /** 获取被保存的备忘录对象 */
public Memento retrieveMemento(int index){
return this.mementos.get(index);
}
}

(4) 测试

public class Client {

    public static void main(String[] args) {

        Originator o = new Originator();
Caretaker c = new Caretaker();
//改变负责人对象的状态
o.setState("On");
//创建备忘录对象,并将发起人对象的状态储存起来
c.saveMemento(o.createMemento());
//修改发起人的状态
o.setState("Off");
c.saveMemento(o.createMemento());
//恢复发起人对象的状态
o.restoreMemento(c.retrieveMemento(1)); System.out.println(o.getState());
}
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

最新文章

  1. Java Class.cast方法
  2. (转载)PHPCMS V9专题路径多了一个斜杠的解决办法
  3. 2016_09_21 Russia is seriously running out of cash_CNN
  4. &lt;实训|第十三天&gt;linux中ACL权限控制以及磁盘配额,附编译属于自己的linux内核
  5. Crontab的格式
  6. DP ZOJ 2745 01-K Code
  7. Swagger 使用方法
  8. 最短路算法 (bellman-Ford算法)
  9. JAVASCRIPT和JQUERY判断浏览器信息总汇(备忘)
  10. easyui中Tab的tools按钮刷新当前tab
  11. [搜片神器]BT管理程序数据库速度调试优化问题
  12. poj2027简单题
  13. 如何实现win7和VirtualBox中Ubuntu系统共享文件夹
  14. mongoDB1--什么是mongoDB
  15. sgu194 Reactor Cooling【无源汇有上下界可行流】
  16. R-FCN论文翻译
  17. Apache Flink 介绍
  18. mysql优化一之查询优化
  19. docker 小技巧 docker network create br-name 指定IP地址
  20. JAVA进阶3

热门文章

  1. BZOJ4025: 二分图【线段树分治】【带撤销的并查集】
  2. animationx详解
  3. flask第二十八篇——HTML【1】table标签
  4. 【thrift】thrift详解
  5. 【转】Notepad++中Windows,Unix,Mac三种格式之间的转换
  6. windows server 2012 AD 域和站点部署系列
  7. 【linux】ls常用参数
  8. eclipse 和 Myeclipse中Maven Web项目出现小红叉的 详细解决方法
  9. 【BZOJ】1801 [Ahoi2009]chess 中国象棋(dp)
  10. Python的设计哲学