基于odoo17的設計模式詳解---備忘模式

大家好,我是你的Odoo技術伙伴。在開發復雜的業務流程時,我們有時會遇到這樣的需求:在對一個對象進行一系列復雜操作之前,保存其當前狀態,以便在操作失敗或用戶希望撤銷時,能夠一鍵恢復到操作之前的樣子。或者,我們需要追蹤一個對象(如一份合同)在不同時間點的所有歷史版本。

實現這種“狀態快照”和“時光倒流”功能的背后,正是我們今天要探討的設計模式——備忘錄模式(Memento Pattern)

一、什么是備忘錄模式?

讓我們從一個大家都很熟悉的場景開始:玩電子游戲時的存檔

  • 你(發起人 Originator): 游戲中的主角,擁有各種狀態(生命值、等級、位置、裝備)。
  • 游戲存檔文件(備忘錄 Memento): 一個包含了你當前所有狀態的“快照”。這個文件本身可能是一個加密的二進制文件,你無法直接看懂或修改它的內容。
  • 游戲系統(負責人 Caretaker): 負責管理所有的存檔文件。它可以讓你創建新存檔、讀取舊存檔,但它不關心存檔文件里的具體內容。

流程是這樣的:

  1. 在挑戰一個強大的BOSS之前,你選擇“保存游戲”。游戲主角(發起人)將自己的當前狀態打包成一個存檔(備忘錄)。
  2. 游戲系統(負責人)接收這個存檔,并將其保存在一個存檔槽里。
  3. 不幸的是,你挑戰失敗了。你選擇“讀取存檔”。
  4. 游戲系統(負責人)從存檔槽里取出之前的存檔文件,并將其交還給游戲主角(發起人)。
  5. 游戲主角(發起人)使用這個存檔文件,將自己的所有狀態恢復到了挑戰BOSS之前的樣子。

備忘錄模式的核心思想是:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣以后就可將該對象恢復到原先保存的狀態。

關鍵在于:

  • 封裝性: 只有發起人自己知道如何創建和恢復備忘錄。負責人和備忘錄本身都無法訪問或修改狀態的細節。
  • 狀態隔離: 對象的狀態被提取出來,獨立于對象本身進行存儲和管理。

二、Odoo中的備忘錄模式:追蹤與審計的基石

在Odoo中,你可能不會顯式地去創建一個Memento類。但是,備忘錄模式的思想被巧妙地應用在了幾個核心功能中,尤其是那些與歷史追蹤版本控制相關的場景。

1. 字段追蹤 (tracking=True) 與 Chatter

這是Odoo中備忘錄模式最直觀、最普遍的應用。當你為一個字段設置tracking=True時,你就啟動了一個針對該字段的“自動存檔”系統。

class SaleOrder(models.Model):_inherit = 'sale.order'# 當 stage_id 字段的值發生變化時,系統會自動創建一個“備忘錄”stage_id = fields.Many2one('sale.order.stage', string='Stage', tracking=True)user_id = fields.Many2one('res.users', string='Salesperson', tracking=True)

讓我們來分解這個場景:

  • 發起人(Originator): sale.order記錄。它擁有stage_iduser_id等內部狀態。
  • 備忘錄(Memento): 當字段值變化時,mail.tracking.value模型中創建的一條新記錄。這條記錄精確地捕獲了“哪個字段,從什么舊值,變成了什么新值”。它就是一個包含了部分狀態變化的“微型快照”。
  • 負責人(Caretaker):
    • Chatter (mail.thread): 它負責“保管”和“展示”這些備忘錄。你在Chatter里看到的“Stage changed from Quotation to Sales Order”這樣的消息,就是負責人對備忘錄的可視化呈現。
    • Odoo的ORM和事務系統: 它們負責在write操作發生時,自動地創建這些備忘錄,并將它們與發起人(sale.order記錄)關聯起來。

這個過程如何體現備忘錄模式?

  • 狀態捕獲: Odoo ORM在保存(write)對象前,檢測到被追蹤字段的變化,并捕獲了其新舊值。
  • 外部存儲: 這個狀態變化信息被存儲在獨立的mail.tracking.value表中,而不是sale.order表自身。
  • 封裝性: sale.order模型并不直接關心這些追蹤記錄是如何存儲的,它只負責在狀態變化時,通過_track_subtype等方法發出一個“需要存檔”的信號。Chatter(負責人)也不知道狀態變化的具體業務含義,它只負責展示。
  • 恢復(概念上): 雖然Odoo的Chatter主要用于審計和追蹤,不提供一鍵“恢復”功能,但它完整地保存了歷史狀態。一個開發者可以基于這些“備忘錄”(追蹤記錄),編寫一個手動的方法來將sale.order恢復到之前的某個狀態。

2. 假設的“草稿版本”功能(自定義實現)

讓我們設想一個更貼近經典備忘錄模式的自定義場景:為復雜的報價單提供“保存草稿”和“恢復草稿”的功能。

假設我們有一個復雜的報價單,用戶在正式發送給客戶前,可能會進行多次修改和測算。我們希望提供一個功能,讓用戶可以隨時保存一個“草稿版本”,并在需要時恢復到這個版本。

# 偽代碼,用于說明思想
import jsonclass Quotation(models.Model):_name = 'sale.quotation'_inherit = ['mail.thread']# ... 報價單的各種字段 ...order_line = fields.One2many(...)# 負責人(Caretaker)的一部分:存儲備忘錄的地方memento_ids = fields.One2many('sale.quotation.memento', 'quotation_id')def create_memento(self, name):"""發起人(Originator)創建備忘錄的方法"""self.ensure_one()# 1. 捕獲內部狀態state_snapshot = {'note': self.note,'payment_term_id': self.payment_term_id.id,'lines': [line.read()[0] for line in self.order_line]}# 2. 創建備忘錄對象,但將狀態封裝在json字段中# 備忘錄本身不知道這些數據的具體含義self.env['sale.quotation.memento'].create({'name': name,'quotation_id': self.id,'state_data': json.dumps(state_snapshot)})def restore_from_memento(self, memento):"""發起人(Originator)從備忘錄恢復狀態的方法"""self.ensure_one()# 1. 從備忘錄獲取狀態數據state_snapshot = json.loads(memento.state_data)# 2. 恢復自身狀態# 只有發起人自己知道如何解讀和應用這些數據self.order_line.unlink() # 先清空舊的行self.write({'note': state_snapshot.get('note'),'payment_term_id': state_snapshot.get('payment_term_id'),'order_line': [(0, 0, line_vals) for line_vals in state_snapshot.get('lines', [])]})class QuotationMemento(models.Model):_name = 'sale.quotation.memento'_description = 'Quotation Snapshot (Memento)'name = fields.Char('Version Name')quotation_id = fields.Many2one('sale.quotation')# 備忘錄的核心:存儲狀態,但不暴露其內部結構state_data = fields.Text('State Data (JSON)', readonly=True)def action_restore(self):"""負責人的一個動作,觸發恢復"""self.quotation_id.restore_from_memento(self)

這個自定義實現完整地展示了備忘錄模式的三個角色及其職責,提供了一個真正的“存檔/讀檔”功能。

三、優勢與適用場景

優勢

  1. 保護封裝性: 將對象的狀態快照功能,從對象本身的核心業務邏輯中分離出來。狀態的保存和恢復細節由發起人自己控制,外部世界(負責人)無法篡改備忘錄的內部。
  2. 簡化發起人: 發起人不需要關心狀態的存儲和管理,它只需要在需要時創建備忘錄或從備忘錄中恢復即可,職責更加單一。
  3. 高內聚,松耦合: 備忘錄模式提供了一種狀態恢復的實現機制,而客戶端(負責人)與這個機制是松耦合的。

適用場景

  • 需要提供一個可撤銷(Undo)或可回滾(Rollback)操作的場景。
  • 需要對一個對象的歷史版本進行追蹤和審計時(如Odoo的tracking功能)。
  • 當需要保存的內部狀態非常復雜,不希望將這些狀態直接暴露給外部時。

結論

備忘錄模式在Odoo中是一種“幕后英雄”式的設計模式。它不像觀察者模式或工廠模式那樣隨處可見,但它在確保數據可追溯性、提供審計日志、以及構建可恢復操作等方面,提供了堅實的設計思想基礎。

Odoo的字段追蹤(tracking=True)功能,就是對備忘錄模式最經典、最成功的應用。它自動地為我們捕獲、存儲和展示了對象狀態變化的“備忘錄”,極大地提升了系統的透明度和可審計性。

作為Odoo開發者,理解備忘錄模式,將幫助你更好地利用Odoo的追蹤功能,并在需要實現“撤銷”或“版本控制”等高級功能時,為你提供一個清晰、可靠的設計思路。

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

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

相關文章

基于Web門戶架構的監獄內網改版實踐:值班排班系統設計與信創適配探討

面向監獄內網改版場景的門戶平臺技術架構與智能排班實踐關鍵詞:監獄內網改版、監獄內部網站改版、值班排班系統、信創適配、智能門戶架構一、場景背景與問題分析 在信創國產化、等級保護合規、政務集約化趨勢持續推進的背景下,傳統監獄內部網站普遍面臨如…

二分查找篇——在排序數組中查找元素的第一個和最后一個位置【LeetCode】

34. 在排序數組中查找元素的第一個和最后一個位置 一、算法邏輯(逐步通順講解每一步思路) 該算法用于在一個升序排列的數組 nums 中查找某個目標值 target 的第一個出現的位置和最后一個出現的位置。 ? 1?? 定義 lower_bound 函數 def lower_boun…

【深度學習新浪潮】AI在材料力學領域的研究進展一覽

一、材料力學的研究范疇 材料力學是固體力學的核心分支,聚焦于材料在載荷作用下的變形、失效規律及性能優化,其核心任務是揭示材料的強度、剛度和穩定性機制。具體研究內容包括: 基本力學行為:分析桿、梁、軸等結構在拉伸、壓縮、彎曲、扭轉等載荷下的應力分布與應變響應。…

WPF之命令

命令的定義:命令與事件的區別:命令是具有約束性的。命令還可以控制接收者"先做校驗,再保存,再關閉"。命令:WPF的命令,實際上就是實現了ICommand接口的類,平時使用最多的是RoutedComma…

百度文心一言開源大模型ERNIE-4.5-0.3B-PT深度測評

號外號外!6月30號,百度文心一言官宣開源ERNIE 4.5大模型!!! 一收到這個消息,博主就立馬從GitCode拉了個模型,本地私有化部署體驗了一下,一個字,酷! 鑒于絕大…

零基礎,使用Idea工具寫一個郵件報警程序

打開idea&#xff0c;創建一個project打開文件目錄下的pom.xml文件&#xff0c;添加下面的內容安裝依賴&#xff0c;等待下載完成<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> &…

字體 Unicode 區塊字符展示 PDF 生成器

Unicode 字體字符集可視化工具 - 代碼介紹 項目概述 這個工具是一個用于分析和可視化字體文件中包含的 Unicode 字符的實用程序&#xff0c;能夠掃描指定字體文件&#xff0c;提取其中包含的所有 Unicode 字符&#xff0c;并按 Unicode 區塊分類生成 PDF 文檔&#xff0c;直觀展…

第4章:實戰項目一 打造你的第一個AI知識庫問答機器人 (RAG)

各位老鐵&#xff0c;歡迎來到我們專欄的第一個實戰項目。 在過去的三個章節里&#xff0c;我們已經完成了所有的理論儲備和環境搭建。我們理解了LLM的本質&#xff0c;掌握了Prompt Engineering的要領&#xff0c;洞悉了Embedding和向量數據庫的魔力&#xff0c;并且熟悉了La…

身份證識別api-便捷生活與安全社會的雙重保障

身份證識別技術是人工智能和圖像處理領域的杰出產物之一&#xff0c;正逐步滲透到我們生活的方方面面。而最直觀的作用就是簡化身份證驗證流程。現如今&#xff0c;無論是銀行開戶、酒店入住還是政務辦理、線上支付&#xff0c;都需要輸入 身份證信息進行身份驗證&#xff0c;傳…

跨國企業進入中國市場:如何利用亞馬遜云科技文檔 MCP 服務器解決區域差異問題

業務場景 想象一下&#xff0c;您是一家美國科技公司的 IT 架構師&#xff0c;公司剛剛決定將業務擴展到中國市場。作為技術負責人&#xff0c;您需要規劃如何將現有的基于亞馬遜云科技的應用遷移到中國區域。然而&#xff0c;您很快發現中國區的云服務環境與您熟悉的全球區域…

WPF使用WebBrowser 解決href標簽target=_blank在瀏覽器窗口打開新鏈接而非窗體內部打開的問題

前言 最近在WPF中使用WebBrowser控件顯示網頁的時候遇到一個問題,由于網頁里面有大規模的連接標簽使用了target=_blank的屬性,導致打開的網頁不是在我們的程序內部,而是調用系統瀏覽器打開了我們的網頁內容,這種情況非常的影響用戶體驗。于是就有了這篇文章內容。本文將詳細…

制作MikTex本地包可用于離線安裝包

MikTex安裝包版本是basic-miktex-24.1-x64.exe。注&#xff1a;basic版本表示只安裝MikTex基本包&#xff0c;不安裝全部包。在能夠聯網的電腦上安裝MikTex軟件后&#xff0c;可以按以下步驟制作本地包庫。一、制作本地包庫1、新建一個文件夾&#xff0c;比如在D盤新建miktex-l…

Redis基礎的介紹與使用(一)(Redis簡介以及Redis下載和安裝)

0 引言 本系列用于和大伙兒一起入門Redis&#xff0c;主要包括Redis的下載&#xff0c;分別在終端&#xff0c;圖形顯示界面以及JAVA代碼中進行使用&#xff0c;適合給需要快速了解Redis是什么以及上手使用的朋友們&#xff0c;希望我用最簡單的語言來講清楚相關內容&#xff…

七牛云C++開發面試題及參考答案

智能指針的原理及應用場景是什么&#xff1f; 智能指針是 C 中用于管理動態分配內存的工具&#xff0c;其核心原理是通過 RAII&#xff08;資源獲取即初始化&#xff09;技術&#xff0c;將堆內存的生命周期與對象的生命周期綁定&#xff0c;從而避免手動管理內存帶來的內存泄…

【Python辦公】Excel橫板表頭轉豎版通用工具(GUI版本)橫向到縱向的數據重構

目錄 專欄導讀前言項目概述功能特性技術棧核心代碼解析1. 類結構設計2. 界面布局設計3. 滾動列表實現4. 數據轉換核心邏輯5. 預覽功能實現設計亮點1. 用戶體驗優化2. 技術實現優勢3. 代碼結構優勢使用場景擴展建議總結完整代碼結尾專欄導讀 ?? 歡迎來到Python辦公自動化專欄—…

C#項目 在Vue/React前端項目中 使用使用wkeWebBrowser引用并且內部使用iframe網頁外鏈 頁面部分白屏

如果是使用wkeWebBrowser的引用方式 非常有可能是版本問題導致的 問題分析 1. wkeWebBrowser 的局限性 不支持或不完全支持 ES6 語法&#xff08;如 let, const, Promise, async/await&#xff09; 缺少對現代 Web API 的支持&#xff08;如 Intl, fetch, WebSocket&#xff0…

系統架構設計師論文分享-論微服務架構

我的軟考歷程 摘要 2023年2月&#xff0c;我所在的公司通過了研發紗線MES系統的立項&#xff0c;該系統為國內紗線工廠提供SAAS服務&#xff0c;旨在提高紗線工廠的數字化和智能化水平。我在該項目中擔任系統架構設計師一職&#xff0c;負責該項目的架構設計工作。本文結合我…

The History of Big Data

數據洪流悄然重塑世界的進程中&#xff0c;大數據的歷史是技術迭代與需求驅動的交響。從 2003 年分布式系統雛形初現&#xff0c;到 Hadoop 掀起開源浪潮&#xff0c;再到 Spark、容器化技術與深度學習的接力革新&#xff0c;以及 Hadoop 生態的興衰起落&#xff0c;大數據發展…

【JS逆向基礎】數據分析之正則表達式

前言&#xff1a;前面介紹了關于JS逆向所需的基本知識&#xff0c;比如前端三件套等&#xff0c;從這里開始就要進入到數據分析的范圍內了&#xff0c;當然對于一些小白而言一些基本的知識還是需要知道的&#xff0c;比如正則&#xff0c;XPATNY與BS4&#xff1b;三個內容用三篇…

Mac mini 高性價比擴容 + Crossover 游戲實測 全流程手冊

Mac mini 高性價比擴容 Crossover 游戲實測 全流程手冊 本文將圖文并茂地指導你如何&#xff1a; 為 M4 Mac mini 外置擴容&#xff08;綠聯 USB4 硬盤盒 致態 TiPlus7100&#xff09;安裝并配置 Crossover/Whisky 運行 Windows 應用實測游戲運行性能、診斷常見異常一、準備工…