Java設計模式之行為型模式(備忘錄模式)實現方式詳解

最近看到一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到網站

一、基礎實現結構

  1. 角色定義與代碼骨架
    備忘錄模式包含三個核心角色,其協作關系如下:
  • Originator(發起人):需保存/恢復狀態的對象,負責創建和使用備忘錄。
  • Memento(備忘錄):存儲發起人狀態的載體,通常設計為不可變類。
  • Caretaker(管理者):管理備忘錄對象,不操作其內容。
    代碼示例(文本編輯器場景):
// 發起人:文本編輯器
public class Editor {private String content;// 創建備忘錄public Memento save() {return new Memento(this.content);}// 從備忘錄恢復狀態public void restore(Memento memento) {this.content = memento.getState();}
}
// 備忘錄:存儲狀態
public class Memento {private final String state;  // 不可變狀態public Memento(String state) { this.state = state; }public String getState() { return state; }
}
// 管理者:保存備忘錄列表
public class History {private List mementos = new ArrayList<>();public void add(Memento memento) { mementos.add(memento); }public Memento get(int index) { return mementos.get(index); }
}
  1. 狀態保存與恢復流程
// 客戶端調用示例
Editor editor = new Editor();
History history = new History();
editor.setContent("Initial text");
history.add(editor.save());  // 保存狀態1
editor.setContent("Modified text");
history.add(editor.save());  // 保存狀態2
// 恢復到狀態1
editor.restore(history.get(0));
System.out.println(editor.getContent());  // 輸出:Initial text

二、高級實現技巧

  1. 封裝性優化
  • 黑箱實現:將Memento作為Originator的內部類,限制外部訪問。
    public class Editor {private String content;// 內部類備忘錄public class EditorMemento {private final String state;private EditorMemento() { this.state = content; }  // 僅內部可訪問}public EditorMemento save() { return new EditorMemento(); }
    }
    
  • 窄接口與寬接口:通過包級私有訪問控制,僅允許Originator讀取Memento內部狀態。
  1. 多狀態管理
    使用棧結構實現撤銷/重做功能:
public class History {private Stack undoStack = new Stack<>();private Stack redoStack = new Stack<>();public void push(Memento memento) { undoStack.push(memento); }public Memento undo() { return undoStack.pop(); }public void redo(Memento memento) { redoStack.push(memento); }
}
  1. 資源優化
  • 增量存儲:僅保存狀態差異而非全量數據。
  • 序列化:通過Serializable接口持久化備忘錄至文件或數據庫。
    // 發起人支持序列化
    public class SerializableOriginator extends Originator implements Serializable {private String state;// 實現序列化邏輯
    }
    

三、實際應用示例

  1. 游戲存檔系統
// 發起人:游戲角色
public class Gamer {private int level;private Inventory items;public GamerMemento save() {return new GamerMemento(level, items.clone());}public void restore(GamerMemento memento) {this.level = memento.getLevel();this.items = memento.getItems();}// 備忘錄類(內部類)public static class GamerMemento {private final int level;private final Inventory items;// 構造函數與Getter}
}
  1. 數據庫事務回滾
public class DatabaseTransaction {private TableData originalData;public TransactionMemento snapshot() {return new TransactionMemento(originalData.clone());}public void rollback(TransactionMemento memento) {this.originalData = memento.getData();}
}

四、測試與調試

  1. 單元測試要點
  • 狀態一致性驗證:使用斷言檢查恢復后的狀態是否與預期一致。
    assertEquals("Initial text", editor.getContent());
    
  • 異常場景測試:模擬空備忘錄或非法恢復操作。
    assertThrows(IllegalStateException.class, () -> editor.restore(null));
    
  1. 性能監控
  • 內存占用分析:通過Profiler工具監控備忘錄對象的數量與大小。
  • 優化策略:限制備忘錄歷史數量(如僅保存最近10個狀態)。

五、常見問題與解決方案

問題解決方案
內存溢出使用LRU算法淘汰舊備忘錄,或采用增量存儲。
狀態不一致確保Memento不可變,避免外部修改。
跨會話恢復失敗將備忘錄序列化至持久化存儲(如文件或數據庫)。

六、總結

備忘錄模式通過狀態快照與封裝隔離機制,為撤銷、回滾等場景提供了靈活的解決方案。實現時需注重:

  1. 職責分離:明確OriginatorMementoCaretaker的邊界。
  2. 資源管理:根據場景選擇內存存儲或持久化方案。
  3. 封裝性保護:通過內部類或訪問控制限制備忘錄訪問。
    該模式廣泛應用于編輯器、游戲、數據庫等領域,是實現無副作用狀態管理的核心工具。

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

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

相關文章

k8s:離線部署tomcatV11.0.9,報Cannot find /opt/bitnami/tomcat/bin/setclasspath.sh

本文記錄了在離線環境下部署Tomcat容器時遇到的權限問題及解決方案。在Docker環境中運行Tomcat時出現&quot;找不到setclasspath.sh&quot;錯誤&#xff0c;通過添加--security-opt seccompunconfined參數解決。在Kubernetes環境中部署時出現相同問題&#xff0c;通過設置…

Linux操作系統之線程(五):線程封裝

目錄 前言 一、線程ID及進程地址空間布局 二、線程棧與線程局部存儲 三、線程封裝 總結&#xff1a; 前言 我們在上篇文章著重給大家說了一下線程的控制的有關知識。 但是如果我們要使用線程&#xff0c;就得那這pthread_create接口直接用嗎&#xff1f;這樣豈不是太過麻…

【物理與機器學習】從非平衡熱力學到擴散模型

[toc] 0.引子:從非平衡熱力學開始 1.架構簡介 2.反向過程的具體推導與 DDPM 改進摘要&#xff1a;擴散模型將非平衡熱力學的“噪聲注入—去噪逆轉”理念注入生成建模中。DDPM&#xff08;Denoising Diffusion Probabilistic Models&#xff09;在 SD2015 的基礎上&#xff0c;通…

Git常用命令詳解:從入門到精通

前言 Git作為當今最流行的分布式版本控制系統&#xff0c;已經成為開發者必備的技能之一。無論你是獨立開發者還是團隊協作&#xff0c;掌握Git的基本操作都能極大提高工作效率。本文將詳細介紹Git的常用命令&#xff0c;幫助你快速上手并精通Git的基本使用。 一、Git基礎概念…

Vue-22-通過flask接口提供的數據使用plotly.js繪圖(一)

文章目錄 1 任務背景 2 Flask提供接口(server.py) 2.1 原始代碼 2.2 跨域問題 3 Vue3獲取數據并渲染Plotly圖表 3.1 新建工程 3.2 程序 3.2.1 index.html(入口) 3.2.2 cpmponents/Plot.vue(子組件) 3.2.3 App.vue(父組件) 3.2.4 main.ts 3.3 展示 4 選擇圖表類型繪圖 4.1 App.v…

【mysql】換主鍵

需求&#xff1a;曲庫表的主鍵錯了&#xff0c;原先設置的是(sang_id),應該設置為&#xff08;sang_name,singer&#xff09;聯合主鍵。-- &#xff08;0&#xff09;先備份數據&#xff0c;我這里沒備份 -- &#xff08;1&#xff09;進行主鍵的切換之前&#xff0c;要進行一些…

Redis原理之緩存

上篇文章&#xff1a; Redis原理之集群https://blog.csdn.net/sniper_fandc/article/details/149141342?fromshareblogdetail&sharetypeblogdetail&sharerId149141342&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目錄 1 Redis作為MySQL…

關于集合的底層數據結構

單列集合Collection分為list集合和set集合list集合分為ArrayList和LinkedListArrayList--底層數據結構是數組1.通過索引查詢快2.增刪要重構索引,增刪慢 LinkedList--底層數據結構是鏈表1.無索引查詢慢2.通過改變前節點的尾指針和后節點的前指針指向可快速增刪,增刪快set集合(…

批量插入技巧:減少事務提交次數的性能提升

一、事務提交成本分析每次事務提交觸發?磁盤I/O同步?&#xff08;WAL機制&#xff09;、?日志寫入?和?鎖資源釋放?操作&#xff0c;高頻獨立提交會產生指數級開銷?。實驗表明&#xff1a;MySQL提交1萬次單條插入比單次批量插入?慢20倍以上??。高頻提交還加劇鎖競爭與…

importlib.import_module() 的用法與實戰案例

&#x1f31f; 一、什么是 importlib&#xff1f; importlib 是 Python 的一個內置標準庫&#xff0c;用于在程序運行時 動態導入模塊。 &#x1f524; 對比&#xff1a;普通 import vs importlib方式示例特點靜態導入import os編寫代碼時就確定要導入的模塊動態導入importlib.…

Oracle 12c 創建數據庫初級教程

1. 連接到Oracle sqlplus / as sysdba Oracle數據庫名稱默認為ORCL或sqlplus /ORCL as sysdba Oracle數據庫名稱默認為ORCL2. 創建表空間&#xff08;數據庫&#xff09; create user YOUR_USERNAME identified by "YOUR_PASSWORD"; YOUR_USERNAME為數據庫名稱和登…

zabbix服務器告警處理

zabbix服務器告警&#xff0c;信息為&#xff1a;Utilization of poller processes over 75%處理辦法為修改zabbix_server.conf配置文件&#xff0c;一般情況下為/etc/zabbix目錄下。根據自己輪詢器的類型修改對應的輪詢器的數量&#xff1b;我這里把StartPollers&#xff0c;S…

隨筆20250721 PostgreSQL實體類生成器

我來幫你創建一個C#程序&#xff0c;從PostgreSQL數據庫讀取表結構并生成對應的實體類文件。我已經創建了一個完整的PostgreSQL實體類生成器。這個程序包含以下主要功能&#xff1a;主要特性數據庫連接: 使用Npgsql連接PostgreSQL數據庫表結構讀取: 自動讀取所有表的結構信息類…

B樹、B-樹與B+樹

B樹、B-tree與B樹 在計算機科學&#xff0c;尤其是數據庫和文件系統的領域中&#xff0c;B樹、B-tree和B樹是理解數據如何被高效存儲和檢索的關鍵。它們之間關系緊密&#xff0c;但功能和應用上又存在著決定性的差異。 一、 核心概念澄清&#xff1a;B樹就是B-tree 首先需要明確…

視頻格式轉換工廠v3.2.5,集音視頻、圖片處理78MB

今天&#xff0c;我們要介紹的是一款功能強大的視頻處理軟件——視頻格式轉換工廠。這款軟件已經完美破解&#xff0c;無需登錄即可享受全部高級功能。它不僅支持視頻格式轉換&#xff0c;還涵蓋了音頻、圖片處理等多種功能&#xff0c;是一款真正的多媒體處理工具。 視頻格式轉…

VUE 中父級組件使用JSON.stringify 序列化子組件傳遞循環引用錯誤

背景 VUE 中父級組件使用JSON.stringify 序列化子組件傳遞的數據會報錯 runtime-core.esm-bundler.js:268 Uncaught TypeError: Converting circular structure to JSON –> starting at object with constructor ‘Object’ — property ‘config’ closes the circle 原因…

HTTP,HTTPS

在網絡工程師、開發工程師、運維工程師等崗位的面試中&#xff0c;??HTTP/HTTPS?? 是高頻必考知識點&#xff0c;尤其在前端、后端、測試、DevOps等與網絡通信相關的職位中。以下是系統化的核心考點梳理&#xff0c;涵蓋基礎概念、協議機制、安全特性及應聘高頻問題。??一…

Nginx訪問日志分析在云服務器環境的技術實現與案例

在云計算時代&#xff0c;Nginx訪問日志分析已成為服務器運維的關鍵環節。本文將深入解析如何通過日志切割、實時監控和可視化展示三大技術路徑&#xff0c;實現云環境下Nginx日志的高效分析。我們將結合具體案例&#xff0c;演示從原始日志到運維決策的完整技術閉環&#xff0…

鴻蒙實現一次上傳多張圖片

記錄初接觸鴻蒙&#xff0c;遇到的一個問題&#xff0c;需求是點擊一個圖片上傳的號圖&#xff0c;訪問本地圖片&#xff0c;可以選擇多張圖片并上傳。下面是圖片上傳后的方法&#xff1a;//選擇圖片并上傳private async showPhotoPicker() {const maxImageCount 3;const rema…

【STM32】CRC 校驗函數

先上一下 CRC校驗 的源代碼&#xff1a; void crc_check(unsigned char *ptr,unsigned int len) //crc為開源函數 {unsigned long wcrc0XFFFF;//預置16位crc寄存器&#xff0c;初值全部為1unsigned char temp;//定義中間變量int i0,j0;//定義計數for(i0;i<len;i)//循環計算每…