行為型模式--Memento模式(備忘錄)對象行為型模式
一. 意圖
在不破壞封裝性的前提下, 捕獲一個對象的内部狀态, 并在該對象之外儲存這個狀态. 這樣以後就可将該對象恢複到原先儲存的狀态.
一個備忘錄(memento)是一個對象, 它存儲另一個對象在某個瞬間的内部狀态, 而後者稱為備忘錄的原發器(originator). 當需要設定原發器的檢查點時, 取消操作機制會向原發器請求一個備忘錄. 原發器用描述目前狀态的資訊初始化該備忘錄. 隻有原發器可以向備忘錄中存取資訊, 備忘錄對其他的對象"不可見".
二. 适用性
必須儲存一個對象在某一個時刻的(部分)狀态, 這樣以後需要時它才能恢複到先前的狀态.
如果一個用接口來讓其它對象直接得到這些狀态,将會暴露對象的實作細節并破壞對象的封裝性.
(當我看到說需要備份一個對象的内部狀态時, 我第一時間就想到, 在對象中公開一個接口用于備份對象的狀态. 其實這樣做是正确的, 但是不能讓所有對象都能使用這個接口來擷取該對象的狀态, 而是使用指定類型的對象, 在該模式中該對象就是Memento類的對象.看 Originator::SetMemento(Memento m))
三. 模式結構

圖1
四. 角色說明
Memento(備忘錄)
—備忘錄存儲原發器對象的内部狀态. 原發器根據需要決定備忘錄存儲原發器的哪些内部狀态.
—防止原發器以外的其他對象通路備忘錄. 備忘錄實際上有兩個接口, 管理者(caretaker)隻能看到備忘錄的窄接口—它隻能将備忘錄傳遞給其他對象. 相反, 原發器能夠看到一個寬接口, 允許它通路傳回到先前狀态所需的所有資料. 理想的情況是隻允許生成本備忘錄的那個原發器通路本備忘錄的内部狀态.
Originator(原發器)
—原發器建立一個備忘錄, 以記錄目前時刻它的内部狀态.
—使用備忘錄恢複内部狀态.
Caretaker(負責人)
—負責儲存好備忘錄.
—不能對備忘錄的内容進行操作或檢查
互動
圖2
五. 說明
1. 保持封裝邊界 使用備忘錄可以避免暴露一些隻應由原發器管理卻又必須存儲在原發器之外的資訊. 該模式把可能很複雜的Originator内部資訊對其他對象屏蔽起來, 進而保持了封裝邊界.
2. 它簡化了原發器. 如果不使用備忘錄模式, 原發器狀态的備份可能需要它自己來存儲.
3. 使用備忘錄可能代價很高, 特别是在原發器的狀态資訊很複雜時, 頻繁的狀态拷貝, 開銷會很大.
4. 維護備忘錄的潛在代價, 管理器負責删除它所維護的備忘錄. 然而, 管理器不知道備忘錄中有多少個狀态. (個人認為既然備忘錄比較熟悉這些狀态, 備忘錄來負責對狀态的删除, 而不是管理器.)
六. 我的了解
1. 備忘錄模式提供了一個很好的方法: 怎樣實作一個對象中的屬性隻對某些對象開放(通過Originator::SetMemento(Memento m)).
2. 看備忘錄模式的結構圖知道, Originator::SetMemento(Memento m)很關鍵, Originator不管理Memento, Memento由Caretaker管理.
3. 當我看到備忘錄模式時, 對比它也是存儲一個對象的某時刻的狀态時, 我想到了Command模式. 因為Command模式實作的功能通常有向前/向後功能(例如菜單操作). 而備忘錄則可以對該功能的狀态存儲提供實作方法.
4. 個人認為, 實作向前/向後功能更關鍵的是你對狀态的分析, 特别是那些影響全局狀态的.
七. 相關模式
Command: 指令可使用備忘錄來為可撤消的操作維護狀态.
Iterator: 如前所述備忘錄可用于疊代.