备忘录(Memento)模式:又叫做快照模式(Snapshot Pattern)或Token模式,属于行为模式。在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
备忘录模式有如下结构图:
备忘录模式涉及角色如下:
发起人(Originator):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
备忘录(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
管理者(Caretaker):负责备忘录Memento,不能对Memento的内容进行访问或者操作。
对上面结构图的代码模拟:
备忘录角色:
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 Originator {
private String state;
public Memento createMemento() {
return new Memento(state);
}
/**
*
* 描述:还原
*/
public void restoreMemento(Memento memento) {
this.state = memento.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
管理者:
public class Caretaker {
private Memento memento;
/**
*
* 描述:取值
*/
public Memento retrieveMemento() {
return memento;
}
/**
*
* 描述:设置
*/
public void saveMemento(Memento 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");
// 创建备忘录对象,并保持于管理保持
c.saveMemento(o.createMemento());
// 改变发起人的状态
o.setState("off");
// 还原状态
o.restoreMemento(c.retrieveMemento());
}
}
对于上述描述中,客户端语句o.createMemento()得到备忘录后,是可以直接获取备忘录中信息的,因为备忘录类没有提供窄接口,这样就破坏了原有的封装性。这种设计备忘录角色的内部所存状态对所有对象是公开的,所以叫做"白箱"实现。有白箱就有黑箱,“黑箱”的实现方式就是利用java双接口的方式来隔离不同的对象访问的。
什么是双接口?就是一个类实现两个接口,不同的类看到的是不同的类型,就像蝙蝠一样,在老鼠一块他就展现的是老鼠的接口;在鸟一块就展现的是鸟的接口。
对于备忘录来说实现双接口,给发起人(Originator)角色展现宽接口,给管理者管理者(Caretaker)提供窄接口。宽接口由Memento本身就可以展现,窄接口只是个标识接口,不提供任何操作的方法。接下来看看如何用双接口方式“ 黑箱”实现。
首先以Memento以标识接口方式提供给除了发起人角色以外的对象,然后把Memento类作为Originaator的内部类,并用private来修饰,保证外部无法操作此类。结构图如下:
标识接口:
//标识接口
public interface IMemento {
}
发起人:
public class Originator {
private String state;
/**
*
* 描述:穿件备忘录
*/
public IMemento createMemento() {
return (IMemento) new Memento(state);
}
/**
* 描述:还原
*/
public void restoreMemento(IMemento memento) {
Memento m = (Memento) memento;
setState(m.getState());
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
System.out.println("current state:" + state);
}
/**
* 描述:内部类
*/
public class Memento implements IMemento {
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 IMemento memento;
/**
* 描述:取值
*/
public IMemento retrieveMemento() {
return memento;
}
/**
* 描述:设值
*/
public void saveMemento(IMemento 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");
// 创建备忘录对象,并保持于管理保持
c.saveMemento(o.createMemento());
// 改变发起人的状态
o.setState("off");
// 还原状态
o.restoreMemento(c.retrieveMemento());
}
}
运行结果:
current state:on
current state:off
current state:on