一、什么是备忘录模式?
备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。
备忘录模式具有的角色:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色。
结构图:
备忘录角色:
(1)将发起人对象的内部状态存储起来,备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态。
(2)备忘录可以保护其内容不被发起人对象之外的任何对象所读取。
(2)备忘录可以保护其内容不被发起人对象之外的任何对象所读取。
备忘录有两个等效的接口:
窄接口:负责人(Caretaker)对象和其他除发起人对象之外的任何对象看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他对象。
宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
窄接口:负责人(Caretaker)对象和其他除发起人对象之外的任何对象看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他对象。
宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
发起人(Originator)角色:
(1)创建一个含有当前的内部状态的备忘录对象。
(2)使用备忘录对象存储其内部状态。
(2)使用备忘录对象存储其内部状态。
负责人(Caretaker)角色:
(1)负责保存备忘录对象。
(2)不检查备忘录对象的内容。
(2)不检查备忘录对象的内容。
二、代码类
//发起人角色代码
public class Originator {
private String state;
public Originator(){}
public MementoIF createMemento(){
return new Memento(this.state);
}
//将发起人恢复到备忘录对象记录的状态
public void restoreMemento(MementoIF memento){
Memento aMemento = (Memento)memento;
this.setState(aMemento.getState());
}
public String getState(){
return this.state;
}
public void setState(String state){
this.state = state;
System.out.println("state="+state);
}
//内部成员类,备忘录
protected class Memento implements MementoIF{
private String savedState;
private Memento(String someState){
savedState = someState;
}
private void setState(String someState){
savedState = someState;
}
private String getState(){
return savedState;
}
}
}
//负责人角色代码
public class Caretaker {
private MementoIF memento;
public MementoIF retrieveMemento(){
return this.memento;
}
public void saveMemento(MementoIF memento){
this.memento = memento;
}
}
//客户端代码
public class Client {
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
public static void main(String []args){
o.setState("on");
//调用发起人角色的createMemento()方法,创建一个备忘录对象将这个状态存储起来。将备忘录对象存储到负责人对象中去。这样负责人并不知道具体的备忘录,而只知道是MementoIF类型,这就是窄接口。
c.saveMemento(o.createMemento());
o.setState("Off");
//将备忘录对象从负责人对象中取出。将发起人对象的状态恢复成备忘录对象所存储起来的状态,即”On”状态。
o.restoreMemento(c.retrieveMemento());
}
}
三、备忘录模式的优缺点
优点:
1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取。这时,使用备忘录可以把复杂的发起人内部信息对其他的对象屏弊起来,从而可以恰当地保持封装的边界。
2、本模式简化了发起人类,发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理它们所需要的这些状态的版本。
3、当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
缺点:
1、如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
2、当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否会昂贵 。