备忘录模式:在不破坏封装性的前提下,破获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的对象。
角色说明
- 原发者:需要在某个时刻保存其状态的对象。原发者负责创建备忘录,然后使用该备忘录记录自己的状态。当原发者需要恢复某个时刻的状态时,它通过获得相应备忘录中的数据来恢复那个时刻的状态,
- 备忘录:负责存储原发者状态的对象,创建备忘录的类和创建原发者的类在同一个包中,该类提供的访问数据的方法都是友好方法,使得只有和原发者在同一包中的类的实例才可以访问备忘录中的数据。
- 负责人:负责管理保存备忘录对象。负责人如果不和原发者在同一个包中,就不能对备忘录中的内容进行修改或读取。
备忘录模式要求原发者可以访问备忘录中的细节,即可以访问备忘录中的数据,以便回复原发者的状态,而负责人只能保存和得到备忘录,但访问备忘录中的数据受到一定的限制。备忘录模式是原发者可以将自己的状态暴露给备忘录,但其他对象想要获得备忘录中的数据会受到一定的限制,这就保证了原发者暴露内部数据的同时,又保证了数据的封装性。
案例
Originator.java
public class Originator { // 原发者(需要保存状态的对象)
private String state; // 状态信息
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
// 编写一个方法可以保存状态对象
public Memento saveMemento() {
return new Memento(state);
}
// 通过备忘录对象恢复对象
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
Memento.java
public class Memento { // 备忘录(负责保存好记录,即Originator的内部状态)
private String state;
public Memento(String state) {
this.state=state;
}
public String getState() {
return state;
}
}
Caretaker.java
public class Caretaker { // 负责人(负责保存多个备忘录对象,使用集合管理提高效率)
// 如果希望保存多个Originator对象的不同时间的状态,也可以,只需要HashMap<String,集合>
private List<Memento> mementos = new ArrayList<Memento>(); // 在这个集合中会有很多的备忘录对象
public void add(Memento memento) {
mementos.add(memento);
}
// 获得到第 index 个 Originator 的备忘录对象
public Memento get(int index) {
return mementos.get(index);
}
}
Application7.java
public class Application7 {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("状态one");
caretaker.add(originator.saveMemento()); // 保存了当前的状态
originator.setState("状态two");
caretaker.add(originator.saveMemento());
originator.setState("状态three");
caretaker.add(originator.saveMemento());
System.out.println("当前的状态是: "+originator.getState());
originator.getStateFromMemento(caretaker.get(0)); // 恢复到状态one
System.out.println("当前的状态是: "+originator.getState());
originator.getStateFromMemento(caretaker.get(2));
System.out.println("当前的状态是: "+originator.getState());
}
}
运行结果
优点
- 强调了类设计单一责任原则,即将状态的刻画和保存分开。
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地会到某个历史状态。
缺点
- 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
适合情景
- Windows的ctrl+z
- 打游戏时的存档
- IE中的后退
- 必须保存一个对象在某一时刻的全部或部分状态,以便在需要时恢复该对象先前的状态。
- 一个对象不想通过提供public权限的,诸如getXXX()的方法让其他对象的到自己的内部状态。