天天看點

C#設計模式(23)——備忘錄模式(Memento Pattern)一、引言二、備忘錄模式介紹三、備忘錄模式的适用場景四、備忘錄模式的優缺點五、總結

   在上一篇博文分享了通路者模式,通路者模式的實作是把作用于某種資料結構上的操作封裝到通路者中,使得操作和資料結構隔離。而今天要介紹的備忘者模式與指令模式有點相似,不同的是,指令模式儲存的是發起人的具體指令(指令對應的是行為),而備忘錄模式儲存的是發起人的狀态(而狀态對應的資料結構,如屬性)。下面具體來看看備忘錄模式。

   從字面意思就可以明白,備忘錄模式就是對某個類的狀态進行儲存下來,等到需要恢複的時候,可以從備忘錄中進行恢複。生活中這樣的例子經常看到,如備忘電話通訊錄,備份操作作業系統,備份資料庫等。

  備忘錄模式的具體定義是:在不破壞封裝的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态,這樣以後就可以把該對象恢複到原先的狀态。

   介紹完備忘錄模式的定義之後,下面具體看看備忘錄模式的結構圖:

C#設計模式(23)——備忘錄模式(Memento Pattern)一、引言二、備忘錄模式介紹三、備忘錄模式的适用場景四、備忘錄模式的優缺點五、總結

  備忘錄模式中主要有三類角色:

發起人角色:記錄目前時刻的内部狀态,負責建立和恢複備忘錄資料。

備忘錄角色:負責存儲發起人對象的内部狀态,在進行恢複時提供給發起人需要的狀态。

管理者角色:負責儲存備忘錄對象。

   下面以備份手機通訊錄為例子來實作了備忘錄模式,具體的實作代碼如下所示:

  具體的運作結果如下圖所示:

C#設計模式(23)——備忘錄模式(Memento Pattern)一、引言二、備忘錄模式介紹三、備忘錄模式的适用場景四、備忘錄模式的優缺點五、總結

  從上圖可以看出,剛開始通訊錄中有3個聯系人,然後移除以後一個後變成2個聯系人了,最後恢複原來的聯系人清單後,聯系人清單中又恢複為3個聯系人了。

  上面代碼隻是儲存了一個還原點,即備忘錄中隻儲存了3個聯系人的資料,但是,如果想備份多個還原點怎麼辦呢?即恢複到3個人後,又想恢複到前面2個人的狀态,這時候可能你會想,這樣沒必要啊,到時候在删除不就好了。但是如果在實際應用中,可能我們發了很多時間去建立通訊錄中隻有2個聯系人的狀态,恢複到3個人的狀态後,發現這個狀态時錯誤的,還是原來2個人的狀态是正确的,難道我們又去花之前的那麼多時間去重複操作嗎?這顯然不合理,如果就思考,能不能儲存多個還原點呢?儲存多個還原點其實很簡單,隻需要儲存多個備忘錄對象就可以了。具體實作代碼如下所示:

  這樣就儲存了多個狀态,用戶端可以選擇恢複的狀态點,具體運作結果如下所示:

C#設計模式(23)——備忘錄模式(Memento Pattern)一、引言二、備忘錄模式介紹三、備忘錄模式的适用場景四、備忘錄模式的優缺點五、總結

   在以下情況下可以考慮使用備忘錄模式:

如果系統需要提供復原操作時,使用備忘錄模式非常合适。例如文本編輯器的Ctrl+Z撤銷操作的實作,資料庫中事務操作。

   備忘錄模式具有以下優點:

如果某個操作錯誤地破壞了資料的完整性,此時可以使用備忘錄模式将資料恢複成原來正确的資料。

備份的狀态資料儲存在發起人角色之外,這樣發起人就不需要對各個備份的狀态進行管理。而是由備忘錄角色進行管理,而備忘錄角色又是由管理者角色管理,符合單一職責原則。

  當然,備忘錄模式也存在一定的缺點:

在實際的系統中,可能需要維護多個備份,需要額外的資源,這樣對資源的消耗比較嚴重。

  備忘錄模式主要思想是——利用備忘錄對象來對儲存發起人的内部狀态,當發起人需要恢複原來狀态時,再從備忘錄對象中進行擷取,在實際開發過程也應用到這點,例如資料庫中的事務處理。