Java行為型模式---備忘錄模式

備忘錄模式基礎概念

備忘錄模式(Memento Pattern)是一種行為型設計模式,其核心思想是在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態,以便后續可以將該對象恢復到先前保存的狀態。備忘錄模式通過將狀態保存和恢復的責任分離,實現了對象狀態管理的封裝和解耦。

備忘錄模式的核心組件

  1. 原發器(Originator)?- 需要保存狀態的對象,負責創建和恢復備忘錄。
  2. 備忘錄(Memento)?- 存儲原發器的內部狀態,通常通過原發器創建并由管理者持有。
  3. 管理者(Caretaker)?- 負責保存備忘錄,但不能對備忘錄的內容進行操作或檢查。

備忘錄模式的實現

下面通過一個文本編輯器的例子展示備忘錄模式的實現:

// 1. 備忘錄類 - 存儲原發器的狀態
class Memento {private final String content;  // 需要保存的狀態public Memento(String content) {this.content = content;}public String getContent() {return content;}
}// 2. 原發器 - 文本編輯器
class TextEditor {private String content;  // 內部狀態public void setContent(String content) {this.content = content;}public String getContent() {return content;}// 創建備忘錄,保存當前狀態public Memento createMemento() {return new Memento(content);}// 從備忘錄恢復狀態public void restoreMemento(Memento memento) {this.content = memento.getContent();}
}// 3. 管理者 - 負責保存備忘錄
class History {private final Stack<Memento> mementos = new Stack<>();  // 使用棧保存歷史狀態public void push(Memento memento) {mementos.push(memento);}public Memento pop() {if (mementos.isEmpty()) {return null;}return mementos.pop();}
}// 4. 客戶端代碼
public class MementoPatternClient {public static void main(String[] args) {TextEditor editor = new TextEditor();History history = new History();// 編輯文本并保存狀態editor.setContent("Hello");history.push(editor.createMemento());editor.setContent("Hello World");history.push(editor.createMemento());editor.setContent("Hello World!");System.out.println("當前內容: " + editor.getContent());  // 輸出: Hello World!// 撤銷操作editor.restoreMemento(history.pop());System.out.println("撤銷一次后的內容: " + editor.getContent());  // 輸出: Hello Worldeditor.restoreMemento(history.pop());System.out.println("再撤銷一次后的內容: " + editor.getContent());  // 輸出: Hello}
}

備忘錄模式的變體

  1. 白箱備忘錄?- 備忘錄的狀態對所有類可見,違反封裝原則,但實現簡單:

    class Memento {private String content;public Memento(String content) {this.content = content;}// 所有類可訪問的公共方法public String getContent() {return content;}public void setContent(String content) {this.content = content;}
    }
    
  2. 黑箱備忘錄?- 使用內部類和接口實現封裝,原發器以外的類無法訪問備忘錄內容:

    interface MementoInterface {// 空接口,僅用于標識
    }class TextEditor {private String content;// 私有內部類實現備忘錄private class EditorMemento implements MementoInterface {private final String savedContent;public EditorMemento(String content) {this.savedContent = content;}private String getSavedContent() {return savedContent;}}public MementoInterface createMemento() {return new EditorMemento(content);}public void restoreMemento(MementoInterface memento) {EditorMemento editorMemento = (EditorMemento) memento;this.content = editorMemento.getSavedContent();}
    }
    
  3. 增量備忘錄?- 只保存狀態變化的部分,節省內存:

    class IncrementalMemento {private final String addedText;private final int position;public IncrementalMemento(String addedText, int position) {this.addedText = addedText;this.position = position;}// 恢復方法由原發器實現
    }
    

備忘錄模式的應用場景

  1. 撤銷 / 重做功能?- 如文本編輯器、圖形設計工具的歷史記錄
  2. 事務管理?- 數據庫操作的回滾機制
  3. 游戲存檔?- 保存游戲進度,支持讀取存檔
  4. 狀態恢復?- 系統崩潰后的恢復點機制
  5. 多級篩選?- 如電商平臺的篩選條件保存與恢復
  6. 瀏覽器歷史?- 網頁瀏覽歷史的前進 / 后退功能

備忘錄模式的優缺點

優點

  • 保持封裝性?- 不破壞對象的封裝前提下保存和恢復其內部狀態
  • 簡化原發器?- 原發器不需要管理自己的歷史狀態,職責更清晰
  • 支持撤銷操作?- 可以方便地實現多級撤銷和重做功能
  • 狀態恢復透明?- 客戶端無需關心狀態的保存細節
  • 符合開閉原則?- 可以在不修改原發器的情況下新增備忘錄類

缺點

  • 資源消耗?- 如果頻繁創建備忘錄,會占用大量內存
  • 性能問題?- 對于大型對象,保存和恢復狀態可能影響性能
  • 管理復雜度?- 管理者需要正確管理備忘錄的生命周期
  • 序列化開銷?- 如果需要跨進程或持久化保存,可能增加序列化復雜度

使用備忘錄模式的注意事項

  1. 控制備忘錄大小?- 避免保存過大的對象狀態,考慮使用增量備忘錄
  2. 限制管理者權限?- 管理者只能保存和傳遞備忘錄,不能修改其內容
  3. 考慮內存管理?- 對于長期保存的備忘錄,需要考慮內存回收策略
  4. 處理復雜對象?- 對于包含引用的對象,需要處理深拷貝和淺拷貝問題
  5. 結合其他模式?- 備忘錄模式常與命令模式結合實現撤銷系統,與迭代器模式結合遍歷歷史狀態
  6. 持久化支持?- 如果需要持久化備忘錄,需考慮序列化和版本兼容性

總結

備忘錄模式通過將對象狀態的保存和恢復封裝在獨立的備忘錄類中,實現了對象狀態管理的解耦和封裝。它在不破壞對象封裝性的前提下,允許對象在需要時恢復到之前的狀態,是實現撤銷 / 重做功能、事務回滾、游戲存檔等場景的理想選擇。在實際開發中,合理使用備忘錄模式可以提高系統的可維護性和用戶體驗,但需要注意控制內存消耗和管理復雜度。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89930.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89930.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89930.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

后端參數校驗

前端給后端傳輸數據&#xff0c;有時候參數需要校驗&#xff0c;我們自己寫代碼會比較麻煩&#xff0c;我們可以使用springboot為我們提供的注解&#xff0c;降低這些沒有必要的代碼開發。1.引入依賴<dependency><groupId>org.springframework.boot</groupId>…

C++ - 仿 RabbitMQ 實現消息隊列--服務端核心模塊實現(一)

目錄 日志打印工具 實用 Helper 工具 sqlite 基礎操作類 字符串操作類 UUID 生成器類 文件基礎操作 文件是否存在判斷 文件大小獲取 讀文件 寫文件 文件重命名 文件創建/刪除 父級目錄的獲取 目錄創建/刪除 附錄&#xff08;完整代碼&#xff09; 日志打印工具 為了便…

C語言:第07天筆記

C語言&#xff1a;第07天筆記 內容提要 循環結構 break與continue 綜合案例《猜拳游戲》數組 數組的概念一維數組流程控制 break與continue break 功能&#xff1a; ① 用在switch中&#xff0c;用來跳出switch中的case語句&#xff1b;如果case沒有break&#xff0c;可能會產生…

qt 中英文翻譯 如何配置和使用

qt 中英文翻譯 如何配置和使用 1. 在.pro文件中添加TRANSLATIONS 在你的 .pro 文件&#xff08;比如 HYAC_AAF_HOST.pro&#xff09;中添加&#xff1a; TRANSLATIONS \ zh\_CN.ts en\_US.ts這會告訴Qt項目你要支持中文和英文。 2. 提取可翻譯文本&#xff08;生成ts文件&#…

Leetcode 710. 黑名單中的隨機數

1.題目基本信息 1.1.題目描述 給定一個整數 n 和一個 無重復 黑名單整數數組 blacklist 。設計一種算法&#xff0c;從 [0, n - 1] 范圍內的任意整數中選取一個 未加入 黑名單 blacklist 的整數。任何在上述范圍內且不在黑名單 blacklist 中的整數都應該有 同等的可能性 被返…

RxJava 全解析:從原理到 Android 實戰

在 Android 開發中&#xff0c;異步任務處理是繞不開的核心場景 —— 網絡請求、數據庫操作、文件讀寫等都需要在后臺執行&#xff0c;而結果需回調到主線程更新 UI。傳統的 “HandlerThread” 或 AsyncTask 不僅代碼冗余&#xff0c;還容易陷入 “回調地獄”&#xff08;嵌套回…

OpenCV 官翻7 - 對象檢測

文章目錄ArUco 標記檢測標記與字典標記物創建標記檢測姿態估計選擇字典預定義字典自動生成字典手動定義字典檢測器參數閾值處理adaptiveThreshConstant輪廓過濾minMarkerPerimeterRate 與 maxMarkerPerimeterRatepolygonalApproxAccuracyRateminCornerDistanceRateminMarkerDis…

【Oracle】ORACLE OMF說明

ORACLE OMF (Oracle Managed Files) 是 Oracle 數據庫提供的一項自動化文件管理功能。它的核心目的是簡化數據庫管理員&#xff08;DBA&#xff09;對數據庫底層操作系統文件的管理工作。 以下是 OMF 的關鍵要點&#xff1a; 核心功能&#xff1a;自動命名和定位文件 在創建數據…

408考研逐題詳解:2010年第35題——RIP協議

2010年第35題 某自治系統內采用 RIP 協議&#xff0c;若該自治系統內的路由器 R1 收到其鄰居路由器 R2 的距離矢量&#xff0c;距離矢量中包含信息 <net1, 16>&#xff0c;則能得出的結論是&#xff08; &#xff09; A. R2 可以經過 R1 到達 net1&#xff0c;跳數為17 …

http與https的主要區別是什么?

什么是HTTP&#xff1f; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本傳輸協議&#xff09;是互聯網上應用最為廣泛的一種網絡協議。它構成了Web數據通信的基礎&#xff0c;并定義了客戶端和服務器之間如何請求和傳遞網頁信息。當您在瀏覽器中輸入一個網址時…

STC89C52系列單片機簡介

STC89C52系列單片機是由中國宏晶科技&#xff08;STC&#xff09;推出的一款新一代增強型8051內核單片機。它不僅繼承了傳統8051指令系統的兼容性&#xff0c;還在性能、功耗、抗干擾能力以及性價比方面進行了全面提升&#xff0c;廣泛應用于各類嵌入式控制場景&#xff0c;如工…

基于 Docker 環境的 JupyterHub 詳細部署手冊

本文詳細介紹基于Docker Compose的單機版JupyterHub部署方案&#xff0c;通過容器化技術實現多用戶Notebook環境的快速搭建。方案采用官方JupyterHub鏡像&#xff0c;配置11個端口映射&#xff08;18000-18010&#xff09;支持用戶并發&#xff0c;通過數據卷掛載&#xff08;.…

常見的萬能密碼

目錄 1. 通用SQL注入 2. 登錄繞過 3. 密碼重置 1. 通用SQL注入 or 11-- " or 11-- or aa " or "a""a or 11# " or 11# or 11/* " or 11/* or 11 " or "1""1 2. 登錄繞過 admin-- admin or 11-- admin or aa …

04訓練windows電腦低算力顯卡如何部署pytorch實現GPU加速

大多數人用的電腦的顯卡配置可能沒有那么強,也就是說,我們很難享受到最新版本pytorch給我們帶來的模型訓練的速度和效率,為此,我們需要想辦法在現有顯卡情況下部署應用pytorch。 筆者有一臺電腦,顯卡算力很低,那么以該電腦為例,為大家介紹如何部署應用pytorch功能。 1…

PPT科研畫圖插件

PPT科研畫圖插件 iSlide- 讓PPT設計簡單起來 | PPT模板下載平臺iSlide - 簡單&#xff0c;好用的PPT插件&#xff01;擁有30萬 原創可商用PPT模板&#xff0c;PPT主題素材&#xff0c;PPT案例&#xff0c;PPT圖表&#xff0c;PPT圖示&#xff0c;PPT圖標&#xff0c;PPT插圖和8…

CSS實現背景圖片漸變透明

復合寫法background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFF 82.5%),url(https://example.com/image.jpg) center / cover no-repeat;參數說明&#xff1a;linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFF 82.5%)創建從下至上的垂直漸變&#xff…

基于pyside6的通用機器人遙控控制界面

1. 前言 這兩天需要幫一個朋友做一個簡單的遙控控制界面&#xff0c;用于控制一臺復合機器人(萬向輪底盤機械臂旋轉云臺)&#xff0c;在這里分享一下 2. 開發框架 由于朋友那邊的控制接口都是使用python來寫的&#xff0c;所以我這里也使用py來完成這個遙控界面的開發。但其…

【iOS】ZARA仿寫

【iOS】ZARA仿寫 文章目錄【iOS】ZARA仿寫前言首頁發現我的對姓名的更改總結前言 暑假第一個的任務仿寫ZARA 雖然不是特別難卻有很多小細節需要注意 首頁 點進程序出現的就是整個項目最主要的一個點&#xff0c;即首頁的無限輪播圖&#xff0c;不管是自動輪播還是手動滑動&a…

Kubernetes Pod 調度基礎

一、Replication Controller 和 ReplicaSet1、Replication ControllerReplication Controller&#xff08;復制控制器&#xff0c;RC&#xff09;RC 用來確保 Pod 副本數達到期望值&#xff0c;這樣可以確保一個或多個同類 Pod 總是可用的。如果存在的 Pod 數量大于設定的值&am…

菜鳥的C#學習(二)

文章目錄一、類的訪問1、普通類繼承抽象類2、普通類繼承抽象類&#xff0c;抽象類繼承接口&#xff0c;三者聯系二、類中方法的訪問2.1 抽象方法和虛方法2.2 虛方法和普通方法**1. 調用機制****2. 方法重寫****3. 設計意圖****4. 性能差異****5. 語法對比表****總結&#xff1a…