在日常开发中,我们经常会遇到这样的场景:需要保存对象的某个历史状态,以便将来恢复。这种需求最常见的例子就是“撤销操作”。在这种情况下,备忘录模式(Memento Pattern)就派上了用场。
目录
1. 概念
备忘录模式属于行为型设计模式。它的核心思想是:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态。
通俗点讲,备忘录模式就像是在玩游戏时存档:你保存了一个状态,之后可以随时“读档”回来。
备忘录模式包含三个关键角色:
1. Originator(发起人):需要保存状态的对象
2. Memento(备忘录):用来存储对象的内部状态
3. Caretaker(管理者):负责保存备忘录,但不会操作或检查其内容
2. 代码实现
这里我将采用一个编辑/撤销文本的案例来实现备忘录模式。
首先我准备一个Editor类
public class Editor {
private String text;
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
// 保存当前状态
public Memento save() {
return new Memento(text);
}
// 恢复状态
public void restore(Memento memento) {
this.text = memento.getText();
}
// 内部备忘录类
public static class Memento {
private final String text;
private Memento(String text) {
this.text = text;
}
private String getText() {
return text;
}
}
}
这里我定义了一个静态内部类即Memento类,主要作为一个备忘录,也是被记录的状态类。
接下来再定义管理者,负责管理备忘录:
import java.util.Stack;
public class History {
private final Stack<Editor.Memento> history = new Stack<>();
public void push(Editor.Memento memento) {
history.push(memento);
}
public Editor.Memento pop() {
if (!history.isEmpty()) {
return history.pop();
}
return null;
}
}
这里我们这个管理类也基于栈来实现,其后进先出的特性可以很好的实现我们需要的写入撤销的业务逻辑。
最后完成一个主测试类:
public class MementoDemo {
public static void main(String[] args) {
Editor editor = new Editor();
History history = new History();
editor.setText("Version 1");
history.push(editor.save());
editor.setText("Version 2");
history.push(editor.save());
editor.setText("Version 3");
System.out.println("当前内容: " + editor.getText()); // 输出 Version 3
editor.restore(history.pop());
System.out.println("撤销后: " + editor.getText()); // 输出 Version 2
editor.restore(history.pop());
System.out.println("再次撤销: " + editor.getText()); // 输出 Version 1
}
}
3. 总结
备忘录模式的封装良好,但其实在实际工作中用到的地方并没有很多,绝大多数的游戏服务器实现存档的功能类似备忘录模式,但是对于后端服务器业务开发过程中,此设计模式的实践并不是很多,大家可以作为了解即可。