备忘录模式:
应用场景:主要是用来防丢失、撤销、恢复等。
定义:在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。
一、备忘录模式是怎么做到不违背封装原则的
备忘录模式的重点在于:不违背封装原则,思考以下两个问题:
- 为什么存储和恢复副本会违背封装原则?
- 备忘录模式是如何做到不违背封装原则的?
典型的备忘录模式实现代码:
第一,通过快照恢复 InputText 对象,在 InputText 类中不可以定义 setText() 函数,因为这个函数有可能会被其他业务使用,从而暴露不应该暴露的函数违背了封装原则。在备忘录模式中,通过restoreSnapshot方法代替,更加见名知意,只用来恢复对象;
第二,快照本身是不可变的,理论上讲,不应该包含任何 set() 等修改内部状态的函数,因此“快照“这个业务模型不可以复用 InputText 类的定义,因为InputText 类本身有一系列修改内部状态的函数。如果在快照类中用 InputText 类来表示快照违背了封装原则。
public class InputText {
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());
}
}
public class Snapshot {
private String text;
public Snapshot(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
public class SnapshotHolder {
private Stack<Snapshot> snapshots = new Stack<>();
public Snapshot popSnapshot() {
return snapshots.pop();
}
public void pushSnapshot(Snapshot snapshot) {
snapshots.push(snapshot);
}
}
public class ApplicationMain {
public static void main(String[] args) {
InputText inputText = new InputText();
SnapshotHolder snapshotsHolder = new SnapshotHolder();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String input = scanner.next();
if (input.equals(":list")) {
System.out.println(inputText.toString());
} else if (input.equals(":undo")) {
Snapshot snapshot = snapshotsHolder.popSnapshot();
inputText.restoreSnapshot(snapshot);
} else {
snapshotsHolder.pushSnapshot(inputText.createSnapshot());
inputText.append(input);
}
}
}
}