一、模式动机
在应用软件的开发过程中,有时我们有必要记录一个对象的内部状态。为了允许用户取消不确定的操作或从错误中恢复过来,需要实现备份点和撤销机制,而要实现这些机制,我们必须事先将状态信息保存在某处,这样状态才能将对象恢复到它们原先的状态。
但是对象通常封装了其部分或所有的状态信息,使得其状态不能被其它对象访问,也就不可能在该对象之外保存其状态,而暴露其内部状态又将违反封装的原则,可能有损系统的可靠性和可扩展性。
二、模式定义
备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
三、模式结构
四、参与者
- Originator:原发器
- Memento:备忘录
- Caretaker:负责人
五、示例代码
package design.pattern;
class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
/**
* 恢复备忘录,将Memento导入并将相关数据恢复
*
* @param memento
*/
public void setMemento(Memento memento) {
this.state = memento.getState();
}
/**
* 创建备忘录,将当前要保存的信息导入并实例化备忘录
*
* @return
*/
public Memento createMemento() {
return new Memento(this.state);
}
/**
* 展示状态数据
*/
public void show() {
System.out.println("当前状态是: " + state);
}
}
public class Memento {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento(String state) {
this.state = state;
}
public static void main(String[] args) {
Originator o = new Originator();
// 初始状态为On
o.setState("On");
o.show();
// 创建备忘录并保存状态
Caretaker caretaker = new Caretaker();
caretaker.setMemento(o.createMemento());
// 更改Originator状态=Off
o.setState("Off");
o.show();
// 恢复到原始状态
o.setMemento(caretaker.getMemento());
o.show();
}
}
class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
优缺点
- 备忘录模式的最大缺点就是资源消耗过大,如果类的成员变量太多,就不可避免占用大量的内存了,而且每保存一次对象的状态都需要消耗内存资源,如果知道这一点大家就容易理解为什么一些提供了Undo功能的软件在运行时需要的内存和硬盘空间比较大了。
模式使用
- 必须保存一个对象在某一个时刻的状态/部分状态,这样以后需要时它能够恢复到先前的状态。
- 如果一个用接口来让其它对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。