备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式,指在不破坏封装性的前提下,获取到一个对象的内部状态,并在对象之外记录或保存这个状态。在有需要的时候可将该对象恢复到原先保存的状态。它适用于对象在执行某些操作为防止意外而在执行操作前将对象状态备份的场景,比如事务回滚,SVN恢复到某个版本等。
备忘录模式的结构图:
从上图可以看出,备忘录模式所涉及的角色有三个:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色:
(1)发起人(Originator):要被备份的成员,它提供一创建备忘录和保存备忘录状态的方法,其实就是将它自身的某些信息拷贝一份到一个备忘录对象中,并提供另外一个方法将备忘录中的信息覆盖自身的信息。
(2)备忘录(Memento):备忘录对象中包含存储发起人状态的成员变量,它提供set,get或构造方法保存发起人状态及获取发起人状态。
(3)管理角色(Caretaker):用于保存备忘录对象。
大家都知道金星曾经是个男人,后来经过变性手术成为了女人。假设现实中有一种技术,可以让金星手术前保存之前“男人”的状态,做了手术后,举得不满意,再恢复成男人。这就是备忘录模式的一个宗旨,可以将某些状态点保存起来,然后根据需要恢复到对应的状态点。我想,如果有这样的技术存在,整容医院会更加受大家青睐的。那么就金星的例子,我完成了以下代码:
发起人角色类,发起人角色利用一个新创建的备忘录对象将自己的内部状态存储起来。
package com.pattern.memento.v1;
/**
* 备忘录发起人:负责创建和恢复备忘录
* @author Jerify
*
*/
public class MementoOriginator {
private String name;//姓名
private String sex;//性别
private int age;//年龄
private float height;//身高
public PersonMemento createMemento(){
return new PersonMemento(this.name,this.sex,this.age,this.height);
}
public void recoveryMemento(PersonMemento memento){
this.name=memento.getName();
this.sex=memento.getSex();
this.age=memento.getAge();
this.height=memento.getHeight();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
}
备忘录角色类,提供各种状态的get、set方法。
package com.pattern.memento.v1;
/**
* 备忘录对象
* @author Jerify
*
*/
public class PersonMemento {
private String name;//姓名
private String sex;//性别
private int age;//年龄
private float height;//身高
public PersonMemento(String name, String sex, int age, float height) {
super();
this.name = name;
this.sex = sex;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
@Override
public String toString() {
return "PersonMemento [name=" + name + ", sex=" + sex + ", age=" + age + ", height=" + height + "]";
}
}
负责人角色类,负责人角色负责保存备忘录对象,但是从不修改(不检查)备忘录对象的内容。
package com.pattern.memento.v1;
/**
* 备忘录负责人:负责保存备忘录对象
* @author Jerify
*
*/
public class MementoCaretaker {
private PersonMemento memento;
public PersonMemento getMememto(){//获取备忘录
return this.memento;
}
public void saveMemento(PersonMemento memento){//保存备忘录
this.memento=memento;
}
}
以上是一个简单的“白箱”备忘录的实现,关于白箱和黑箱备忘录的区别,在此不赘述了,请参考博文:http://www.cnblogs.com/java-my-life/archive/2012/06/06/2534942.html
(1)将对象状态备份,便于在出现意外时进行状态回滚。
(2)对象状态的副本交由管理器(Caretaker)管理,发起人无需管理状态的备份。而在还原状态时,又由发起人自己执行状态还原方法,外界无法获取发起人的备份状态信息从而保证了备份数据的安全性。
备忘录模式的缺点:
将对象状态备份会占用较多的系统资源。
源码下载:http://download.youkuaiyun.com/download/pelifymeng2/9994744