备忘录模式:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,后续可以把对象恢复到原先保存的状态。 角色:
Originator(发起人):需要保存状态的对象,可以创建备忘录,也可以恢复状态
Memento(备忘录):存储发起人的内部状态,只允许发起人访问
Caretaker(管理者):负责保存备忘录,不对备忘录内容操作
/**
* 备忘录 Memento:保存发起人状态,私有构造,仅Originator可访问
*/
class Memento {
// 保存的状态
private final String state;
// 构造方法私有化,只有同包Originator能创建
Memento(String state) {
this.state = state;
}
String getState() {
return state;
}
}
/**
* Originator 发起人:文本编辑器,可以保存快照、恢复快照
*/
class Editor {
private String content;
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
// 创建备忘录(保存当前状态)
public Memento saveToMemento() {
return new Memento(this.content);
}
// 从备忘录恢复状态
public void restoreFromMemento(Memento memento) {
this.content = memento.getState();
}
}
/**
* Caretaker 备忘录管理者:负责保管备忘录对象,不读取内部状态
*/
class Caretaker {
private Memento memento;
public void saveMemento(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return memento;
}
}
// 测试客户端
public class MementoDemo {
public static void main(String[] args) {
Editor editor = new Editor();
Caretaker caretaker = new Caretaker();
// 编辑文本
editor.setContent("第一版内容:Java设计模式");
System.out.println("当前编辑器内容:" + editor.getContent());
// 保存快照
caretaker.saveMemento(editor.saveToMemento());
System.out.println(">>> 已经保存备忘录快照");
// 修改内容
editor.setContent("第二版内容:备忘录模式 Memento,修改后的文字");
System.out.println("修改后编辑器内容:" + editor.getContent());
// 恢复快照
editor.restoreFromMemento(caretaker.getMemento());
System.out.println("恢复快照后内容:" + editor.getContent());
}
}
输出结果
当前编辑器内容:第一版内容:Java设计模式
>>> 已经保存备忘录快照
修改后编辑器内容:第二版内容:备忘录模式 Memento,修改后的文字
恢复快照后内容:第一版内容:Java设计模式
扩展:多版本历史记录(保存多个快照)
Caretaker 使用 List 存储多个备忘录,实现撤销多次操作:
import java.util.ArrayList;
import java.util.List;
class CaretakerMulti {
private final List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
class MementoMultiDemo {
public static void main(String[] args) {
Editor editor = new Editor();
CaretakerMulti caretaker = new CaretakerMulti();
editor.setContent("版本1");
caretaker.add(editor.saveToMemento());
editor.setContent("版本2");
caretaker.add(editor.saveToMemento());
editor.setContent("版本3");
System.out.println("当前:" + editor.getContent());
// 回退到版本1
editor.restoreFromMemento(caretaker.get(0));
System.out.println("回退到版本1:" + editor.getContent());
}
}
要点说明
封装保护:
Memento构造方法包访问权限,外部不能 new 备忘录,防止外部篡改保存的状态。职责分离:Originator 读写状态;Memento 只存数据;Caretaker 只负责保管,不解析备忘录内容。
适用场景:撤销操作、快照备份、历史版本回退。
缺点:状态很多时备忘录对象占用内存大。
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问