1. 意圖
在不破壞封裝性的前提下,捕獲對象內部狀態並在該對象外部保存,以便日後恢復到該狀態。
2. 別名
Token
3. 動機
需實現「撤銷」、「檢查點」等功能時,必須保存對象歷史狀態。若直接暴露內部狀態供外部存取,會破壞封裝;Memento 模式將狀態存儲職責轉移給專門的備忘錄對象,發起人決定保存什麼,管理者只負責保管,不檢查內容。
4. 適用性
- 必須保存對象在某時刻的(部分)狀態,以便後續恢復。
- 若用接口讓其他對象直接獲取狀態,會暴露實現細節並破壞封裝。
5. 結構角色
| 角色 | 職責 |
| Originator(發起人) | 創建備忘錄,記錄當前狀態;可從備忘錄恢復狀態。 |
| Memento(備忘錄) | 存儲發起人內部狀態,防止除發起人外的對象訪問。 |
| Caretaker(管理者) | 負責保管備忘錄,不可操作/檢查其內容。 |
6. 代碼示例(Java)
// 發起人
public class Originator {
private String state;
public void setState(String s) { state = s; }
public String getState() { return state; }
public Memento createMemento() { return new Memento(state); }
public void restoreMemento(Memento m) { state = m.getState(); }
}
// 備忘錄
public class Memento {
private final String state;
public Memento(String s) { state = s; }
public String getState() { return state; }
}
// 管理者
public class Caretaker {
private Memento memento;
public void setMemento(Memento m) { memento = m; }
public Memento getMemento() { return memento; }
}
// 測試
public class Test {
public static void main(String[] args) {
Originator o = new Originator();
o.setState("egg");
Caretaker c = new Caretaker();
c.setMemento(o.createMemento()); // 備份
o.setState("niu"); // 修改
System.out.println("修改後: " + o.getState());
o.restoreMemento(c.getMemento()); // 恢復
System.out.println("恢復後: " + o.getState());
}
}
輸出
修改後: niu
恢復後: egg
7. 相關模式
- Command:命令對象可用 Memento 實現撤銷。
- Iterator:迭代器狀態可用 Memento 保存。
8. 實戰提示
- Memento 可序列化到磁盤/數據庫實現持久化撤銷。
- 大對象時,備忘錄只存增量變化或關鍵字段,避免內存爆炸。
- Caretaker 可管理多個 Memento(如堆棧)實現多級撤銷/重做。
- 上一篇文章: Acdream 1113 The Arrow:概率 DP 求期望骰子次數
- 下一篇文章: 行為型設計模式:State(狀態)模式完整指南
Copyright ©
程式碼之家 All Rights Reserved