Go設(shè)計模式--備忘錄模式,帶暫存的業(yè)務(wù)功能可以參考它來實現(xiàn)
大家好,這里是每周都在陪你一起進步的網(wǎng)管~!今天繼續(xù)學(xué)習(xí)設(shè)計模式—備忘錄模式
備忘錄模式(Memento Pattern)又叫作快照模式(Snapshot Pattern), 或令牌模式(Token Pattern), 指在不破壞封裝的前提下, 捕獲一個對象的內(nèi)部狀態(tài), 并在對象之外保存這個狀態(tài)。 這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài), 屬于行為型設(shè)計模式。
備忘錄模式主要適用于以下應(yīng)用場景。
- 需要保存歷史快照的場景。
- 希望在對象之外保存狀態(tài),且除了自己,其他類對象無法訪問狀態(tài)保存的具體內(nèi)容。
備忘錄模式是一種行為型設(shè)計模式。這種模式允許我們保存對象在某些關(guān)鍵節(jié)點時的必要信息,以便于在適當(dāng)?shù)臅r候可以將之恢復(fù)到之前的狀態(tài)。通常它可以用來幫助設(shè)計撤銷/恢復(fù)操作。
備忘錄模式的類結(jié)構(gòu)
下面是備忘錄模式的類圖,
圖片來自https://refactoringguru.cn/design-patterns/memento,我后面實現(xiàn)的時候不會完全按照這個結(jié)構(gòu)去實現(xiàn),這里先把結(jié)構(gòu)里的各個角色給大家說清楚。
備忘錄模式中主要有這三個角色的類
- Originator(發(fā)起者):Originator是當(dāng)前的基礎(chǔ)對象,它會將自己的狀態(tài)保存進備忘錄,此角色可以類比博客系統(tǒng)中的文章對象
- 發(fā)起者中要有保存方法和從備忘錄中恢復(fù)狀態(tài)的方法,保存方法會返回當(dāng)時狀態(tài)組成的備忘錄對象
- Memento(備忘錄) : 存儲著Originator的狀態(tài)的對象,類比理解即為文章對象的不同版本。
- Caretaker(管理人):Caretaker是保存著多條備忘錄的對象,并維護著備忘錄的索引,在需要的時候會返回相應(yīng)的備忘錄 -- 類比理解為博客系統(tǒng)中的編輯器對象
管理者的保存和恢復(fù)操作,會代理其持有的發(fā)起者對象的保存和恢復(fù)操作,在這些代理方法中會增加對備忘錄對象列表、當(dāng)前備忘錄版本的維護。
上面這個類圖結(jié)構(gòu)是實現(xiàn)備忘錄模式的最簡單方式,真實使用的時候,Caretaker,Originator、memento 這些角色可以繼續(xù)抽象出對應(yīng)的接口和實現(xiàn)。這里就不搞那么復(fù)雜了,要舉的例子比較簡單,這么一拆顯得這個模式用起來特別費事兒。
其實其他設(shè)計模式也是一樣,學(xué)習(xí)的時候大家知道了它的結(jié)構(gòu)后,在實現(xiàn)應(yīng)用的環(huán)節(jié)不必完完全全按照結(jié)構(gòu)一板一眼地全部進行實現(xiàn),有的應(yīng)用場景并不復(fù)雜,能合并的角色可以按需進行合并。
應(yīng)用舉例
場景
某線上博客平臺, 需為用戶提供在線編輯文章功能,文章主要包括標(biāo)題 - title 和內(nèi)容 - content等信息。為最大程度防止異常情況導(dǎo)致編輯內(nèi)容的丟失, 需要提供版本暫存和Undo, Redo功能。
"版本暫存"問題可以應(yīng)用備忘錄模式, 將編輯器的狀態(tài)完整保存起來(主要就是編輯內(nèi)容),Undo和Redo的本質(zhì), 是在歷史版本中前后移動把當(dāng)時保存的內(nèi)容加載到文章對象上。
方案設(shè)計
- IEditor: 定義編輯器接口
- EditorMemento: 定義編輯器的備忘錄, 也就是編輯器的內(nèi)部狀態(tài)數(shù)據(jù)模型, 同時也對應(yīng)一個歷史版本
- Editor: 編輯器類, 實現(xiàn)IEditor接口
這個例子里我們把原發(fā)器和管理人兩個角色集中在Editor類型上一起實現(xiàn),例子比較簡單,就沒有單獨實現(xiàn)一個Article類型作為原發(fā)器角色,如果你想完全按照備忘錄模式的結(jié)構(gòu)實現(xiàn),把Title、Content這寫屬性和Save方法抽離到單獨的Article類型上,再讓Editor嵌套組合Article即可。
下面我們根據(jù)UML類圖實現(xiàn)一下這個帶Undo、Redo功能的編輯器。
代碼實現(xiàn)
首先在IEditor 接口里定義編輯器對象要實現(xiàn)的行為
接下來定義編輯器的備忘錄, 也就是編輯器的內(nèi)部狀態(tài)數(shù)據(jù)模型, 同時也對應(yīng)一個歷史版本。
然后是最復(fù)雜的Editor實現(xiàn),它會實現(xiàn)上面IEditor接口中定義的所有行為,其中的Undo、Redo方法即回退、前進方法在實現(xiàn)的時候就是依賴的它內(nèi)部記錄的一組Memento對象,通過指向不同的Memento對象來實現(xiàn)回退和前進功能。
最后我們來測試一下Editor的版本記錄功能
運行程序后會有類似下面的顯示