**备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。**
备忘录模式所涉及的角色有三个:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色。
备忘录角色有如下责任:
1、将发起人对象的内战状态存储起来。备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态。
2、备忘录可以保护其内容不被发起人对象之外的任何对象所读取。
备忘录有两个等效的接口:
1、窄接口:负责人对象(和其他除发起人对象之外的任何对象)看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他的对象。
2、宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
发起人角色有如下责任:
1、创建一个含有当前的内部状态的备忘录对象。
2、使用备忘录对象存储其内部状态。
负责人角色有如下责任:
1、负责保存备忘录对象。
2、不检查备忘录对象的内容。
“白箱”备忘录模式的实现
备忘录角色对任何对象都提供一个接口,即宽接口,备忘录角色的内部所存储的状态就对所有对象公开,因此这个实现又叫做“白箱实现”。
“白箱”实现将发起人角色的状态存储在一个大家都看得到的地方,因此是破坏封装性的。但是通过程序员自律,同样可以在一定程度上实现模式的大部分用意。因此白箱实现仍然是有意义的。
发起人角色类:
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
System.out.println("当前状态:"+this.state);
}
/**
* 工厂方法,返回一个新的备忘录对象
* @return
*/
public Memento createMemento(){
return new Memento(state);
}
/**
* 将发起人恢复到备忘录对象所记载的状态
* @param memento
*/
public void restoreMemento(Memento memento){
this.state = memento.getState();
}
}
备忘录角色类:
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
负责人角色类:
public class Caretaker {
private Memento memento;
/**
* 备忘录的取值方法
* @return
*/
public Memento retrieveMemento(){
return this.memento;
}
/**
* 备忘录的赋值方法
* @param memento
*/
public void saveMemento(Memento memento){
this.memento = memento;
}
}
客户端角色类:
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");
//恢复发起人对象的状态
o.restoreMemento(c.retrieveMemento());
System.out.println(o.getState());
}
}
在上面这个示意性的客户端角色里,首先将发起人对象的状态设置为”On”,并创建一个备忘录对象这个状态存储起来;然后将发起人对象的状态改为”Off”,最后又将发起人对象恢复到备忘录对象他所存储起来的状态,即”On”状态。
备忘录角色对发起人角色对象提供一个宽接口,而为其他对象提供一个窄接口。这样的实现叫做“黑箱实现”。
在JAVA语言中,实现双重接口的办法就是将备忘录角色类设计成发起人角色类的内部成员类。
将Memento设成Originator类的内部类,从而将Memento对象封装在Originator里面;在外部提供一个标识接口MementoIF给Caretaker以及其他对象。这样,Originator类看到的是Memento的所有接口,而Caretaker以及其他对象看到的仅仅是标识接口MementoIF所暴露出来的接口。