模式介绍
- 备忘录模式(Memento Pattern)在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
- 可以这里理解备忘录模式:现实生活中的备忘录是用来记录某些要去做的事情,或者是记录已经达成的共同意见的事情,以防忘记了。在软件层面,备忘录模式有着相同的含义,备忘录对象主要用来记录一个对象的某种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作。
- 备忘录模式属于行为型模式
UML类图
类图解析:
- Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
- Memento(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
- Caretaker(管理者):负责备忘录Memento,不能对Memento的内容进行访问或者操作。
备忘录模式案例
背景介绍: 以上面的UML为例,设计一个小游戏存档恢复系统
Originator类
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
/**
* 保存状态
*/
public Memento save() {
return new Memento(getState());
}
/**
* 恢复状态
*/
public void resume(Memento memento) {
state = memento.getState();
}
}
Memento类
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
Caretaker类
public class Caretaker {
private List<Memento> mementos = new ArrayList<>();
/**
* 添加状态
*/
public void addState(Memento memento) {
System.out.println("添加存档:" + memento.getState());
mementos.add(memento);
}
/**
* 获取状态
*/
public Memento getState(int index) {
Memento memento = mementos.get(index);
System.out.println("恢复存档:" + memento.getState());
return memento;
}
}
Client测试类
public class Client {
public static void main(String[] args) {
// 游戏开始
Originator originator = new Originator();
// 游戏存档
Caretaker caretaker = new Caretaker();
// 游戏进度
originator.setState("剩余100点血");
System.out.println("++通过第一关,前往第二关++");
caretaker.addState(originator.save());
originator.setState("剩余75点血");
System.out.println("++通过第二关,前往第三关++");
caretaker.addState(originator.save());
originator.setState("战败~~");
caretaker.addState(originator.save());
System.out.println("++请选择恢复存档店++");
System.out.println("++1.第二关开始100点血 2.第三关开始75点血++");
System.out.print("请选择:");
Scanner scanner = new Scanner(System.in);
switch (scanner.next()) {
case "1":
System.out.println("恢复第二关开始存档点");
originator.resume(caretaker.getState(0));
break;
case "2":
System.out.println("恢复第二关开始存档点");
originator.resume(caretaker.getState(1));
break;
default:
System.out.println("退出~");
break;
}
}
}
测试结果:
备忘录模式优缺点
优点
- 保存与被保存状态处于关键对象的外面,有助于维护内聚。
- 保存关键对象的数据封装。
- 提供容易实现的恢复能力。
缺点
- 备忘与用于保存状态。
- 使用备忘录,保存和恢复状态可能相当耗时。
- 在Java系统中考虑使用序列化(Serialization 即单例模式)来保存对象的状态。