1. 备忘录模式介绍
备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装的情况下捕获对象的内部状态,并在以后将该对象恢复到这个状态。它的主要目的是保存对象的历史状态,以便在需要时能够恢复。这种模式对于实现撤销操作或者在某些情况下需要回滚到之前的状态特别有用。
类比场景: 想象一下你正在写一篇文章,你会在某个时刻保存当前的内容,以便如果不满意后续的修改,可以回到之前保存的版本。备忘录模式就像是这种“保存”和“撤销”的功能。
结构组成:
- 发起人(Originator):拥有内部状态并可以创建备忘录以保存状态。
- 备忘录(Memento):存储发起人的内部状态。备忘录的内容对其他对象是不可见的。
- 负责人(Caretaker):负责保存备忘录,但不操作或检查备忘录的内容。
优缺点分析:
- 优点:
- 可以在不破坏封装的情况下保存和恢复对象的状态。
- 简化了撤销和恢复操作的实现。
- 备忘录可以保存对象的完整状态,便于恢复。
- 缺点:
- 如果对象的状态非常复杂,可能会导致备忘录占用大量内存。
- 发起人和备忘录之间可能需要进行深拷贝操作,影响性能。
适用场景:
- 需要实现撤销和恢复功能的编辑器或应用程序。
- 需要保存对象状态以便在未来某个时刻进行恢复的场合。
- 在进行复杂计算或操作时,可能需要回到某个中间状态的情况。
2. 代码演示
演示场景:模拟文章编辑器,存储多个文件版本,并在需要的时候恢复到某个版本。
发起人(Originator):
// 发起人类: 拥有内部状态(content), 并可以创建备忘录以保存状态
public class Editor {
private String content;
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
//创建备忘录以保存状态
public EditorMemento save() {
return new EditorMemento(content);
}
//使用备忘录恢复状态
public void restore(EditorMemento memento) {
this.content = memento.getContent();
}
}
备忘录(Memento):
// 备忘录类:存储发起人的内部状态。
// 备忘录的内容对其他对象是不可见的,只与 发起人(Originator)和 负责人(Caretaker)打交道
public class EditorMemento {
private final String content;
public EditorMemento(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
负责人(Caretaker):
// 负责人类:负责保存备忘录,但不操作或检查备忘录的内容
// 这里使用栈结构保存数据
public class Caretaker {
private Stack<EditorMemento> mementoStack = new Stack<>();
// 保存发起人(Originator)的备忘录
public void save(Editor editor) {
mementoStack.push(editor.save());
}
//恢复发起人(Originator)的数据
public void undo(Editor editor) {
if (!mementoStack.isEmpty()) {
editor.restore(mementoStack.pop());
}
}
}
客户端使用代码:
// 客户端使用示例:客户端不感知备忘录类(EditorMemento),即备忘录的内容对其他对象是不可见的
public class MementoClientDemo {
public static void main(String[] args) {
Editor editor = new Editor();
Caretaker caretaker = new Caretaker();
editor.setContent("Version 1");
caretaker.save(editor);
editor.setContent("Version 2");
caretaker.save(editor);
editor.setContent("Version 3");
System.out.println("Current Content: " + editor.getContent());
caretaker.undo(editor);
System.out.println("After Undo: " + editor.getContent());
caretaker.undo(editor);
System.out.println("After Second Undo: " + editor.getContent());
}
}
对应的类图: