目錄
定義
類圖
角色
角色詳解
(一)發起人角色(Originator)?
(二)備忘錄角色(Memento)?
(三)備忘錄管理員角色(Caretaker)?
優缺點
優點?
缺點?
使用場景
可回滾的操作場景?
游戲存檔場景?
需要監控的副本場景?
定義
????????備忘錄模式,英文名為 Memento Pattern,是 GoF(Gang of Four,即設計模式領域的四位大師:Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides)提出的 23 種經典設計模式之一,屬于行為型設計模式范疇。其核心定義為:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。如此一來,后續便能夠將該對象恢復到先前保存的狀態。?
????????打個比方,我們在使用繪圖軟件時,可能會進行一系列的繪圖操作,如繪制圖形、填充顏色、調整線條粗細等。如果沒有備忘錄模式,一旦我們操作失誤,比如不小心刪除了重要圖形或者對顏色填充不滿意,可能就很難恢復到之前理想的狀態。但有了備忘錄模式,繪圖軟件就可以在每次關鍵操作前,將當前畫布的狀態(即對象的內部狀態,包括繪制的圖形、顏色設置、線條樣式等)捕獲并保存起來。當我們想要撤銷操作時,軟件就能從這些保存的狀態中取出對應的狀態,將畫布恢復到之前的樣子。
類圖
角色
????????備忘錄模式的類圖主要涉及三個核心角色,它們相互協作,共同實現了對象狀態的保存與恢復功能。?
-
發起人角色(Originator):這一角色在類圖中處于核心地位,它就像是一個擁有自主記憶能力的個體。發起人角色負責記錄當前時刻自身的內部狀態,同時具備創建和恢復備忘錄數據的關鍵能力。在代碼實現層面,它通常會有一個方法用于創建備忘錄,將自身當前的狀態信息打包存儲到備忘錄對象中;另外還會有一個方法,當需要恢復狀態時,從傳入的備忘錄對象中提取信息,恢復自身的狀態。例如,在一個游戲角色類中,游戲角色就是發起人角色,它可以創建一個備忘錄來記錄自己當前的等級、生命值、裝備等狀態,也能夠從一個已有的備忘錄中讀取這些信息,恢復到之前保存的狀態。?
-
備忘錄管理員角色(Caretaker):可以把備忘錄管理員角色看作是一個細心的圖書管理員,它負責對備忘錄進行管理,包括保存和提供備忘錄。然而,它并不直接操作備忘錄中的內容,僅僅起到一個中間協調和管理的作用。在類圖中,它與備忘錄角色和發起人角色都有一定的關聯,它從發起人角色那里獲取備忘錄對象并妥善保存,當發起人角色需要恢復狀態時,再將對應的備忘錄對象提供給發起人角色。比如在游戲存檔系統中,備忘錄管理員角色可能會將游戲角色創建的備忘錄(記錄了游戲角色的各種狀態)存儲到硬盤的特定位置,當玩家需要讀取存檔恢復游戲角色狀態時,它再從存儲位置取出對應的備忘錄提供給游戲角色(發起人角色)。
-
備忘錄角色(Memento):備忘錄角色如同一個精心設計的容器,專門用于存儲發起人角色的內部狀態。為了確保封裝性,它通常會對狀態信息進行合理的封裝,防止外部對象隨意訪問和修改。在類圖中,備忘錄角色與發起人角色緊密關聯,發起人角色能夠訪問備忘錄角色中存儲的詳細狀態信息,而其他外部角色則只能看到備忘錄角色提供的有限接口,無法直接窺探和篡改其中的狀態數據。以繪圖軟件為例,備忘錄角色可能會存儲畫布上所有圖形的坐標、形狀、顏色等詳細信息,這些信息對于繪圖軟件的核心邏輯(發起人角色)來說是可訪問的,以便在需要時進行狀態恢復,但對于外部的普通用戶操作接口來說,是不可見且不可隨意修改的。?
角色詳解
(一)發起人角色(Originator)?
-
狀態記錄:發起人角色需要精確地記錄自身當前時刻的內部狀態。這要求它對自身的各個屬性和狀態有清晰的認知,并能夠將這些信息以一種可存儲的方式整理出來。例如,在一個財務記賬系統中,記賬本對象作為發起人角色,需要記錄當前的賬目余額、每一筆交易的明細(包括交易時間、金額、對方賬戶等)等內部狀態信息。?
-
備忘錄創建:發起人角色擁有創建備忘錄的能力,它將當前記錄好的內部狀態信息封裝到一個備忘錄對象中。這個過程就像是把一本書的所有內容整理好后放進一個文件袋里。在代碼實現上,通常會創建一個備忘錄類的實例,并將自身的狀態信息賦值給備忘錄類的相應屬性。比如,在一個文本編輯器中,文本對象作為發起人角色,當需要創建備忘錄時,它會將當前文本的內容、光標位置、字體設置等信息封裝到一個備忘錄對象中。?
-
狀態恢復:當需要恢復到之前保存的狀態時,發起人角色能夠從傳入的備忘錄對象中提取相應的狀態信息,并將自身的狀態恢復到備忘錄所記錄的狀態。這就如同從文件袋中取出書,重新閱讀并按照書中記錄的內容調整自身狀態。例如,在一個圖形設計軟件中,圖形對象作為發起人角色,當接收到一個包含之前圖形狀態信息的備忘錄對象時,它會讀取備忘錄中的圖形形狀、顏色、位置等信息,將自身的圖形狀態恢復到對應的樣子。?
(二)備忘錄角色(Memento)?
-
狀態存儲:備忘錄角色的主要職責就是安全、可靠地存儲發起人角色的內部狀態。它會根據發起人角色的狀態信息結構,設計相應的屬性來存儲這些信息。例如,在一個游戲角色的備忘錄中,會有屬性來存儲角色的等級、生命值、魔法值、背包物品清單等信息。這些屬性通常會被設置為私有的,以保證狀態信息的封裝性,防止外部非法訪問和修改。?
-
訪問控制:為了維護封裝性,備忘錄角色會對狀態信息的訪問進行嚴格控制。對于發起人角色,它提供足夠的接口,使得發起人能夠讀取和設置狀態信息,以便進行狀態恢復操作。但對于其他外部角色,只提供非常有限的接口,甚至不提供任何接口,避免外部對象隨意獲取和篡改備忘錄中的狀態信息。比如,在一個數據庫事務的備忘錄中,只有數據庫事務處理模塊(發起人角色)能夠直接訪問備忘錄中記錄的事務狀態、數據修改內容等信息,而其他無關的業務模塊則無法直接訪問這些敏感信息。?
(三)備忘錄管理員角色(Caretaker)?
-
備忘錄保存:備忘錄管理員角色負責接收發起人角色創建的備忘錄對象,并將其妥善保存起來。保存的方式可以有多種,比如存儲在內存中的數據結構里(如列表、棧等),或者存儲到外部存儲設備(如硬盤、數據庫)中。在一個文檔編輯軟件中,當用戶進行保存操作時,文檔對象(發起人角色)創建一個備忘錄記錄當前文檔的狀態,備忘錄管理員角色則將這個備忘錄存儲到硬盤上的特定文檔版本管理目錄中。?
-
備忘錄提供:當發起人角色需要恢復狀態時,備忘錄管理員角色能夠準確地找到并提供相應的備忘錄對象給發起人角色。這就要求備忘錄管理員角色在保存備忘錄時,有合理的索引和管理機制,以便能夠快速定位到需要的備忘錄。例如,在一個版本控制系統中,備忘錄管理員角色會根據版本號等信息,將對應的備忘錄提供給需要恢復到特定版本狀態的文件對象(發起人角色)。
優缺點
優點?
-
狀態恢復機制:備忘錄模式為用戶提供了一種極為便捷的狀態恢復機制。在許多應用場景中,用戶可能會因為誤操作或者想要嘗試不同的操作路徑,而需要回到之前的某個狀態。例如在文檔編輯過程中,用戶可能不小心刪除了重要段落,通過備忘錄模式實現的撤銷功能,就可以輕松恢復到刪除前的狀態;在圖形設計中,對某個圖形的操作不滿意,也能利用備忘錄模式回到操作前的狀態。這種狀態恢復機制極大地提高了用戶體驗,減少了用戶因為錯誤操作而產生的焦慮和時間浪費。?
-
信息封裝性:通過將對象的內部狀態封裝在備忘錄對象中,備忘錄模式實現了良好的信息封裝。外部對象無法直接訪問和修改發起人對象的內部狀態,只有發起人對象自身能夠通過備忘錄對象來管理和恢復自己的狀態。這不僅提高了系統的安全性,防止了外部非法操作對對象內部狀態的破壞,還使得系統的結構更加清晰,各模塊之間的耦合度降低。例如,在一個企業資源規劃(ERP)系統中,財務模塊的內部狀態(如賬目余額、成本核算數據等)通過備忘錄模式進行封裝,其他業務模塊無法直接訪問和修改這些敏感信息,保證了財務數據的準確性和安全性。?
-
簡化發起人類:備忘錄模式減輕了發起人類的負擔,使其不再需要自行管理和保存自身內部狀態的多個版本。在沒有使用備忘錄模式時,發起人類可能需要維護復雜的數據結構來記錄自身的狀態變化歷史,這會增加代碼的復雜性和維護成本。而采用備忘錄模式后,發起人只需要專注于自身的核心業務邏輯,狀態的保存和管理工作由備忘錄角色和備忘錄管理員角色來完成。比如,在一個游戲角色類中,原本可能需要在游戲角色類內部維護一個復雜的狀態棧來記錄每次升級、戰斗后的狀態變化,使用備忘錄模式后,游戲角色類只需要在需要時創建和恢復備忘錄,狀態的存儲和管理工作交給了備忘錄和備忘錄管理員。?
缺點?
-
資源消耗問題:如果發起人角色的狀態數據量較大,并且需要頻繁地創建和保存備忘錄,那么在資源消耗方面會面臨較大壓力。每個備忘錄對象都需要占用一定的內存空間,如果長時間積累大量的備忘錄,可能會導致內存不足等問題。例如,在一個大型 3D 建模軟件中,模型對象的狀態(包括復雜的幾何形狀、材質紋理、光照設置等)數據量巨大,每保存一次狀態就會生成一個龐大的備忘錄對象,如果用戶頻繁進行保存操作,會迅速消耗大量的內存資源。?
-
存儲容量不確定性:備忘錄管理員角色在保存備忘錄時,往往難以預先知道一個備忘錄對象會占用多大的存儲空間。這就可能導致在存儲管理方面出現問題,比如在有限的硬盤空間中,可能因為不斷保存備忘錄而導致空間不足,但又無法提前提醒用戶某個操作會產生較大的存儲開銷。例如,在一個手機游戲中,游戲存檔(即備忘錄)的大小可能會因為玩家在游戲中的不同行為(如收集大量物品、解鎖復雜劇情等)而有很大差異,游戲開發者很難準確預估每個存檔的大小,這可能會給玩家帶來存儲空間不足的困擾。?
-
狀態有效性問題:當發起人角色的狀態發生改變時,新的狀態并不一定總是有效的。在這種情況下,如果頻繁使用備忘錄模式進行狀態恢復,可能會導致系統陷入一種混亂的狀態。而且,如果狀態改變的成功率較低,頻繁地保存和恢復備忘錄可能并不是一個高效的解決方案,不如采用其他更合適的設計模式,如 “假如” 協議模式(在執行操作前先假設操作成功,進行一系列模擬操作,若實際操作失敗再進行回滾等處理)。例如,在一個金融交易系統中,每一筆交易操作都可能改變賬戶的狀態,但交易過程中可能會因為各種原因(如網絡故障、賬戶余額不足等)導致交易失敗,如果頻繁使用備忘錄模式來恢復交易前的賬戶狀態,可能會影響系統的穩定性和交易效率。
使用場景
可回滾的操作場景?
-
文本編輯軟件:像我們日常使用的 Word、WPS 等文本編輯軟件,其中的撤銷(Ctrl + Z)和重做(Ctrl + Y)功能就是備忘錄模式的典型應用。在我們輸入文字、修改格式、刪除內容等操作過程中,文本編輯軟件會在每次關鍵操作前創建一個備忘錄,記錄當前文檔的狀態。當我們按下撤銷鍵時,軟件就從之前保存的備忘錄中取出對應的狀態,將文檔恢復到上一個操作前的狀態;按下重做鍵時,則從后續保存的備忘錄中獲取狀態,將文檔恢復到撤銷前的狀態。?
游戲存檔場景?
-
游戲存檔是備忘錄模式最為人熟知的應用場景之一。在各種類型的游戲中,玩家在游戲過程中會不斷改變游戲角色的狀態(如等級提升、裝備獲取、任務進度推進等)。為了讓玩家能夠在后續繼續游戲時從之前保存的進度開始,游戲系統會在玩家進行存檔操作時,創建一個備忘錄記錄游戲角色的當前狀態,包括角色的各項屬性(生命值、魔法值、攻擊力等)、背包中的物品、所處的游戲地圖位置、完成的任務列表等信息。當玩家讀取存檔時,游戲系統從對應的備忘錄中獲取這些信息,將游戲角色恢復到存檔時的狀態,讓玩家能夠繼續之前的游戲體驗。例如,在一款大型角色扮演游戲中,玩家經過長時間的探索和戰斗,到達了一個關鍵的游戲場景,此時玩家選擇存檔。之后,當玩家再次打開游戲讀取存檔時,游戲角色會以存檔時的狀態出現在之前的游戲場景中,玩家可以繼續后續的游戲冒險。?
-
綜上所述,備忘錄模式在軟件開發的眾多領域中都有著廣泛而重要的應用,它為我們提供了一種強大的狀態管理和恢復機制,雖然存在一些缺點,但在合適的場景下合理運用,能夠顯著提升系統的質量和用戶體驗。在實際的軟件設計和開發過程中,我們需要根據具體的業務需求和系統特點,權衡利弊,決定是否采用備忘錄模式來解決狀態管理相關的問題。
-
系統配置管理:在大型企業級系統中,系統配置的正確性對于系統的穩定運行至關重要。為了防止因為錯誤的配置修改導致系統故障,系統配置管理模塊可以采用備忘錄模式。在每次對系統配置進行修改前,創建一個備忘錄記錄當前的配置狀態。如果修改后的配置導致系統出現問題,就可以從備忘錄中恢復到之前正確的配置狀態。比如,在一個云計算平臺中,對服務器的網絡配置、資源分配策略等進行修改時,利用備忘錄模式可以保證在出現問題時能夠快速回滾到穩定的配置狀態。?
需要監控的副本場景?
-
數據庫事務管理:數據庫事務是指作為單個邏輯工作單元執行的一系列操作,這些操作要么全部成功,要么全部失敗。在數據庫事務處理中,備忘錄模式被廣泛應用于事務的回滾操作。當開始一個事務時,數據庫系統會創建一個備忘錄,記錄事務開始前數據庫的狀態(包括數據的版本、鎖的狀態等)。如果在事務執行過程中出現錯誤,系統就可以根據備忘錄中的信息將數據庫恢復到事務開始前的狀態,保證數據的一致性和完整性。例如,在一個銀行轉賬事務中,當從一個賬戶扣除金額并向另一個賬戶添加金額的過程中,如果出現網絡故障等問題,就可以利用備忘錄模式回滾事務,確保兩個賬戶的金額不會出現錯誤的變動。?
-
命令行操作:在操作系統的命令行界面中,有時我們可能會連續執行多個命令,當發現某個命令執行錯誤時,希望能夠回滾到之前的系統狀態。一些先進的命令行工具就采用了備忘錄模式,記錄每次命令執行前系統的關鍵狀態(如文件系統狀態、環境變量等),當用戶執行撤銷命令時,能夠恢復到之前正確的狀態。?
-
圖形設計軟件:在 Adobe Photoshop、Sketch 等圖形設計軟件中,用戶對圖形的繪制、變形、顏色調整等操作都可以通過備忘錄模式實現可回滾。比如,當我們對一個圖層進行了復雜的濾鏡處理后,發現效果不理想,就可以利用備忘錄模式撤銷濾鏡操作,恢復圖層原來的狀態。這種可回滾操作極大地提高了圖形設計的靈活性和創作效率,讓設計師能夠更加大膽地嘗試各種設計思路。?