備忘錄模式(Memento Pattern)是一種行為設計模式,用于捕獲對象的內部狀態并在需要時恢復該狀態,同時不破壞對象的封裝性。它適用于需要實現撤銷/重做、歷史記錄或狀態快照的場景。
核心組件
Originator(原發器)
- 需要保存狀態的對象
- 提供創建備忘錄和恢復狀態的方法
- 示例代碼:
public class TextEditor {private String content;public void write(String text) {this.content = text;}// 創建備忘錄public TextMemento save() {return new TextMemento(content);}// 從備忘錄恢復public void restore(TextMemento memento) {this.content = memento.getSavedContent();} }
Memento(備忘錄)
- 存儲 Originator 的內部狀態
- 通常設計為不可變對象
- 示例代碼:
public final class TextMemento {private final String content;public TextMemento(String content) {this.content = content;}// 僅允許原發器訪問String getSavedContent() {return content;} }
Caretaker(管理者)
- 負責保存和管理備忘錄
- 不能修改備忘錄內容
- 示例代碼:
import java.util.Stack;public class History {private final Stack<TextMemento> states = new Stack<>();public void saveState(TextMemento state) {states.push(state);}public TextMemento getLastState() {return states.pop();} }
工作流程
graph LRA[Originator] -- 創建 --> B[Memento]B -- 存儲 --> C[Caretaker]C -- 提供 --> AA -- 恢復狀態 --> B
關鍵特性
封裝保護
- Memento 通過私有訪問控制保護狀態
- Caretaker 只能存儲備忘錄,不能修改內容
狀態管理
- 支持多級撤銷:使用棧結構存儲歷史狀態
- 狀態隔離:每個備忘錄獨立存儲對象快照
內存優化
- 增量存儲:僅保存變化部分
- 懶加載:需要時再生成備忘錄
適用場景
- 需要實現撤銷/重做功能(如文本編輯器)
- 需要保存對象歷史狀態(如游戲存檔)
- 需要隔離狀態生成和存儲邏輯
優缺點分析
優點
- 保持對象封裝邊界
- 簡化原發器職責(SRP原則)
- 支持多狀態管理
缺點
- 可能增加內存消耗
- Caretaker 需維護生命周期
- 頻繁保存可能影響性能
擴展實現
// 客戶端使用示例
public class Client {public static void main(String[] args) {TextEditor editor = new TextEditor();History history = new History();editor.write("First draft");history.saveState(editor.save()); // 保存狀態1editor.write("Revised content");history.saveState(editor.save()); // 保存狀態2editor.restore(history.getLastState()); // 撤銷到狀態1}
}
設計建議
- 對大型對象使用增量備忘錄
- 通過接口約束備忘錄訪問權限
- 結合原型模式優化狀態克隆性能
- 使用對象池管理頻繁創建的備忘錄