备忘录模式(Memento)
备忘录模式是一种行为设计模式,
它允许在不暴露对象实现细节(封装原则)的情况下保存和恢复对象之前的状态。
优点:
缺点:
可以灵活的各种实现,只要不破坏原有封装即可,如:
也可以针对备忘录进行优化,如利用**“增量备份”**的方式来节省内存消耗。
实现时要注意深度拷贝的问题。
原发器 (Originator) 类
public class StringUtil {
private StringBuilder text = new StringBuilder();
public String getText() {
return text.toString();
}
public void append(String input) {
text.append(input);
}
/**
* 生成自身状态的快照
*/
public Snapshot createSnapshot() {
return new Snapshot(text.toString());
}
/**
* 通过快照恢复自身状态
*/
public void restoreSnapshot(Snapshot snapshot) {
this.text.replace(0, this.text.length(), snapshot.getText());
}
}
备忘录 (Memento)
public class Snapshot {
private String text;
/**
* 备忘录(Memento)是原发器状态快照的值对象(value object)。
* 通常做法是将备忘录设为不可变的,并通过构造函数一次性传递数据。
*/
public Snapshot(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
负责人 (Caretaker)
public class SnapshotHolder {
/**
* 也可以叫做 history ,负责人通过保存备忘录栈来记录原发器的历史状态。
*/
private Stack<Snapshot> snapshots = new Stack<>();
/**
* 负责人通过保存备忘录栈来记录原发器的历史状态。
*/
public void save(StringUtil stringUtil){
snapshots.push(stringUtil.createSnapshot());
}
/**
* 当原发器需要回溯历史状态时,负责人将从栈中获取最顶部的备忘录,并将其传递给原发器的恢复方法。
*/
public void undo(StringUtil stringUtil){
stringUtil.restoreSnapshot(snapshots.pop());
}
}
测试代码
public class MementoTest {
@Test
public void test() {
StringUtil stringUtil = new StringUtil();
SnapshotHolder snapshotHolder = new SnapshotHolder();
stringUtil.append("张三");
snapshotHolder.save(stringUtil);
Assertions.assertEquals("张三",stringUtil.getText());
stringUtil.append("是法外狂徒");
Assertions.assertEquals("张三是法外狂徒",stringUtil.getText());
// 发现输错了 撤销一下
snapshotHolder.undo(stringUtil);
Assertions.assertEquals("张三",stringUtil.getText());
stringUtil.append("李四");
snapshotHolder.save(stringUtil);
Assertions.assertEquals("张三李四",stringUtil.getText());
}
}
以上代码与文章会同步到 github 仓库:
/chenbihao/Design-Patterns