备忘录模式
备忘录模式(Memento Pattern)是一种行为型设计模式,用于在不破坏对象封装性的前提下,捕获并保存一个对象的内部状态,以便在需要时恢复到该状态。它常用于需要实现撤销(undo)或恢复(restore)功能的情景,比如文本编辑器的撤销操作、游戏存档等。
备忘录模式的组成
备忘录模式通常包含以下几个角色:
- 发起人(Originator):需要保存状态的对象。它负责创建备忘录(存储当前状态)并在需要时使用备忘录恢复状态。
- 备忘录(Memento):存储发起人内部状态的对象。通常只提供有限的访问接口(如只允许发起人访问其状态)。
- 管理者(Caretaker):负责保存备忘录,但不操作或检查备忘录的内容。它只负责传递和存储备忘录。
工作原理
- 发起人创建一个备忘录,保存当前状态。
- 管理者接收并存储这个备忘录。
- 当需要恢复状态时,发起人从管理者获取备忘录,并用其恢复到之前的状态。
UML 类图
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Originator │ │ Memento │ │ Caretaker │
├────────────────┤ ├────────────────┤ ├────────────────┤
│ state │<----->│ state │ │ mementoList │
│ createMemento()│ │ getState() │ │ addMemento() │
│ setMemento() │ │ setState() │ │ getMemento() │
└────────────────┘ └────────────────┘ └────────────────┘
代码示例(以 Java 为例)
以下是一个简单的备忘录模式实现,模拟文本编辑器的撤销功能:
// 备忘录类,存储状态
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人类,管理状态并创建/恢复备忘录
class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("当前状态: " + state);
}
public String getState() {
return state;
}
public Memento createMemento() {
return new Memento(state);
}
public void setMemento(Memento memento) {
state = memento.getState();
System.out.println("恢复状态到: " + state);
}
}
// 管理者类,负责存储备忘录
class Caretaker {
private Memento memento;
public void setMemento(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return memento;
}
}
// 测试代码
public class Main {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
// 设置初始状态
originator.setState("状态1");
// 保存状态到备忘录
caretaker.setMemento(originator.createMemento());
// 修改状态
originator.setState("状态2");
// 恢复之前的状态
originator.setMemento(caretaker.getMemento());
}
}
输出:
当前状态: 状态1
当前状态: 状态2
恢复状态到: 状态1
备忘录模式的特点
- 优点:
- 提供了一种状态恢复机制,适合需要撤销或回滚的场景。
- 保持封装性,备忘录的内部状态对外部对象不可见。
- 缺点:
- 如果状态数据量大,保存备忘录可能消耗较多内存。
- 增加了系统的复杂性,需要额外管理备忘录对象。
使用场景
- 需要保存和恢复对象状态的场景,如:
- 文本编辑器的撤销功能。
- 游戏中的存档和读档。
- 数据库事务的回滚。
- 需要在不破坏对象封装性的情况下保存状态。
注意事项
- 备忘录的访问权限需要严格控制,通常只允许发起人访问其内部状态。
- 如果需要保存多个状态点,可以在管理者中使用列表(如
List<Memento>
)来存储多个备忘录。 - 在实际应用中,可以结合其他模式(如命令模式)实现更复杂的撤销/重做功能。
总结
备忘录模式通过分离状态保存与恢复的职责,实现了状态的外部化管理,同时保护了对象的封装性。它在需要历史状态管理的场景中非常实用,尤其适合实现撤销功能或状态回溯的系统。