当前位置: 首页 > news >正文

[設計模式]二十三種設計模式

"組件協作"模式

組件協作: 實現框架與應用程序的劃分, 通過晚綁定來實現框架與應用程序之間的松耦合, 是二者之間協作時常用的模式

  • 晚綁定: 從設計者去綁定用戶的代碼, 而不是用戶去綁定設計者的代碼

模板方法模式(Template Method)

模板方法模式: 定義算法的骨架(穩定), 將一些步驟延遲(變化)到子類中, 使子類可以不改變(複用)算法的結構即可重定義(override 重寫)該算法的某些特定步驟。

  • 設計者設計好整個流程, 穩定的部分直接由設計者負責, 而變化的部分由用戶負責

實現: 設計者把穩定的部分實現(比如某一個步驟、run函數來負責整個運行的流程), 而把變化的部分設計為虛函數(通常是protected), 而用戶繼承設計者的類, 再實現虛函數, 最後調用設計者預設的運行函數(run函數等)

使用時機: 算法的流程穩定, 但是具體步驟的實現細節變化, 那麼就適合使用模板方法模式, 比如oat++, 它提供了HTTP服務器的流程, 但具體的實現細節從用戶自行實現

特點:

  • 晚綁定: 從設計者去綁定用戶的代碼, 而不是用戶去綁定設計者的代碼
  • 靈活性低: 程序的流程由設計者決定, 而用戶只能調用設計者提供的開始接口
  • 易編寫: 客戶只需要實現虛函數, 不需要自己編寫執行流程。使用"不要調用我, 讓我調用你"的反向控制結構

策略模式(Strategy)

策略模式: 定義一系統算法, 把它們一個個封裝起來, 并且使它們可互相替換(變化)。該模式使得算法可獨立於使用它的客戶程序(穩定)而變化(擴展, 子類化)

  • 設計者確定好策略(契約), 使用子類實現具體策略類, 用戶根據契約的內容, 使用設計者實現的行為

實現: 使用接口定義好策略(契約), 通過子類實現契約的功能, 用戶通過多態去使用對應的具體策略類

使用時機:

  • 算法的流程穩定, 但流程中的某個獨立步驟存在多種不同的實現方式(變化)
  • 需要使用條件判斷語句的地方, 可以通過多態來直接區分情況, 但如果是穩定的條件判斷, 那麼就不需要使用策略模式

特點:

  • 易擴展: 需要新的實現細節, 可以直接使用子類去實現, 不需要修改接口的方法
  • 客戶職責增加: 用戶必須需要全部的策略, 才能正確地使用對應的策略實例

觀察者模式(Observer/Event)

觀察者模式: 定義對象間一對多(變化)的依賴關係, 以便當一個對象的狀態發生改變時, 所有依賴於它的對象都能得到通知并自動更新

  • 目標發送通知時, 無需指定觀察者, 通知(可以携帶通知信息作為參數)會自動傳播
  • 觀察者自己決定是否需要訂閱通知, 目標對象對此一無所知

實現: 對象存儲依賴它的對象的信息, 當狀態改變時, 通知依賴它的對象, 也就是調用依賴它的對象的方法

使用時機: 一個對象的改變需要觸發其他多個對象的動作


"單一職責"模式

"單一職責"模式: 劃清責任, 在軟件組件的設計中, 如果責任劃分的不清晰, 使用繼承得到的結果往往是隨著需求的變化, 子類急劇膨脹, 同時充斥著重復代碼


裝飾模式(Decorator)

裝飾模式: 動態(組合)地給一個對象增加一些額外的職責。就增加功能而言, Decorator模式比生成子類(繼承)更為靈活(消除重復代碼&減少子類個數)

  • 裝飾: 為組件(接口)提供新的功能(職責), 相當於裝飾組件(加上新的東西上去)

實現: 主要看裝飾者和具體裝飾者, 實際上可以沒有裝飾者直接使用具體裝飾者也能接受

  • 組件: 接口
  • 具體組件: 實現接口的原始對象類, 被裝飾的對象
  • 裝飾者: 抽象類(因為需要組合組件), 通常繼承組件同時組合組件
    • 繼承: 讓裝飾者偽裝成一個組件, 那麼一個裝飾者也可以被另一個裝飾者繼續包裹, 那麼就可以疊加不同的職責, 而不用新寫一個疊加對應職責的具體裝飾者
    • 組合: 裝飾者只實現新增的功能, 本來組件的功能由具體組件實現
  • 具體裝飾者: 為組件添加新的職責, 它的方法通常會實現新的職責再調用組合組件的方法

使用時機: 透明地為一個對象增加職責, 特別是需要新增多個職責的情況下


橋模式(Bridge)

橋模式: 將抽象部分(業務功能)與實現部分(平台實現)分離, 使它們都可以獨立地變化

  • : 連接兩個類, 抽象功能組合實現部分

實現:

  • 實現部分: 接口
  • 抽象部分: 抽象類, 其中有著實現部分的接口的指針

使用場景: 當一個類有著多個不同維度的方向, 那麼就需要把每個維度的方向獨立出來


"對象創建"模式

"對象創建"模式: 解開new的緊耦合, 來避免對象創建(new)過程中所導致的緊耦合,(依賴具體類) 從而支持對象創建的穩定


工廠模式

工廠模式: 定義一個用於創建對象的接口, 讓子類決定實例化哪一個類, Factory Method使得一個類的實例化延遲(目的: 解耦, 手段: 虛函數)到子類

  • 把new部分的依賴, 從子類中調離, 而進行參數的方式指定

實現:

  • 組件: 接口

  • 具體組件: new部分使用工廠組件的函數, 其中工廠組件實例從參數傳入

  • 工廠組件: 接口

  • 具體工廠組件: 返回對應的具體組件

  • 產品 (Product):定義了工-廠方法所創建對象的接口。

  • 具體產品 (Concrete Product):實現 Product 接口。

  • 創建者 (Creator):一個抽象類,聲明了返回 Product 對象的工廠方法(通常是純虛函數)。它通常還包含依賴於該工廠方法的、使用產品的業務邏輯。

  • 具體創建者 (Concrete Creator):重寫工廠方法,以返回一個具體產品的實例。

使用時機: 創建對象的程式碼與使用對象的程式碼分離開時。


抽象工廠模式

抽象工廠模式: 提供一個接口, 讓該接口負責創建一系列"相關或者相互依賴的對象", 無需指定它們具體的類

  • 和工廠模式的分別是幾個對象之間有關係, 也就是幾個對象應該以特定的方式組合在一起

實現:

  • 抽象工廠 (Abstract Factory)
    • 這是一個接口。
    • 它聲明了一組用於創建抽象產品的方法。每個方法對應一個產品。
  • 具體工廠 (Concrete Factory)
    • 實現了 Abstract Factory 接口。
    • 它負責創建一整套具體的產品。工廠內部的每個創建方法都會返回一個具體的產品實例。
  • 抽象產品 (Abstract Product)
    • 這也是一個接口。
    • 它為某一種類型的產品(例如,按鈕、CPU)定義了公共接口。
  • 具體產品 (Concrete Product)
    • 實現了 Abstract Product 接口。
    • 它們是由具體工廠創建的對象。同一個具體工廠創建的所有產品,構成了一個「產品族」
  • 客戶端 (Client)
    • 只使用 Abstract Factory 和 Abstract Product 的接口。
    • 它與任何具體的工廠或產品類完全解耦。

使用時機: 需要生成一系統有關係的工廠方法


原型模式

原型模式: 使用原型實例指定創建對象的種類, 然後通過拷貝這些原型來創建新的對象

實現:

  • 原型: 抽口, 有著clone方法
  • 具體原型: 實現clone方法

使用時機: 需要創建多個構建流程複雜的類, 在創建一個之後把它作為原型, 不斷生成對象

  • 比如創建進程fork

構建器模式

構建器模式: 將一個複雜對象的構建與其表示相分離, 使得相同的構建過程(穩定)可以創建不同的表示(變化)

實現:

  • 構建器: 接口, 聲明構建步驟
  • 具體構建器
  • 組件: 複雜對象, 有著很多的構建方法
  • 指導者: 封裝構建流程, 但實際上很少使用, 因為這樣就固定了整個流程, 需要組件間有著類似的流程才可以使用, 導致復用性很低

使用時機: 分離對象的構建和使用


對象性能模式

"對象性能"模式: 針對創建很多對象的性能問題


單件模式

單件模式: 保證一個類僅有一個實例, 并提供一個該實例的全局訪問點

實現:

  • static: C++11及以後版本, 確保了函數內的靜態局部變量的初始化是線程安全的, 所以可以直接使用static修飾變量, 最後返回靜態局部變量
  • 雙重檢查鎖模式: 為了線程安全和性能要求, 所以需要有原語來確保線程安全和兩次判斷條件確保性能要求
// 這是 DCLP 的一種實現,試圖通過精細的內存序來優化性能
Singleton* Singleton::getInstance() {Singleton* tmp = m_instance.load(std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_acquire); // 獲取 fenceif (tmp == nullptr) { // 第一次檢查(在鎖外)std::lock_guard<std::mutex> lock(m_mutex);tmp = m_instance.load(std::memory_order_relaxed);if (tmp == nullptr) { // 第二次檢查(在鎖內)tmp = new Singleton;std::atomic_thread_fence(std::memory_order_release); // 釋放 fencem_instance.store(tmp, std::memory_order_relaxed);}}return tmp;
}

使用場景: 管理全局唯一的資源, 比如日志、配置文件等

  • 但使用依賴注入是更好的方式

享元模式

享元模式: 運用共享技術有效地支持大量細粒度的對象

實現: 對象池記錄全部的元件, 在使用的時候直接在對象池中尋找, 不存在的話加入進對象池

使用場景: 大量的對象, 如果可以區分出能共享和獨立的數據, 那麼就可以把共享的數據記錄起來


接口隔離模式

"接口隔離"模式: 在組件構建過程中,某些接口之間直接的依賴常常會帶來很多問題、甚至根本無法實現。採用添加一層間接(穩定)接口,來隔離本來互相緊密關聯的接口是一種常見的解決方案。


門面模式

門面模式: 為子系統中的一組接口提供一個一致(穩定)的界面, 門面模式定義了一個高層接口, 這個接口使得這一子系統更加容易使用(複用)

  • 解耦: 隔離組件和組件的關係, 組件只需要知道另一組件的門面, 而不需要知道內部細節

實現:

  • 門面類: 組合需要用的部分, 實現簡化調用流程

使用場景:

  • 當你想為一個複雜的庫或框架提供一個簡單的接口時(例如,封裝一個複雜的第三方庫)。
  • 當你想將系統劃分為多個層次時,可以使用門面來定義每個層次與其他層次交互的唯一入口。
  • 當一個遺留系統過於複雜,你想為其提供一個更清晰的接口時。

代理模式

代理模式: 為其他對象提供一種代理, 用於控制(隔離, 使用接口)對這個對象的訪問

  • 附加行為: 不改變原始對象核心行為的前提下,為其提供訪問控制或管理的附加行為。

實現:

  • 主題: 接口
  • 具體主題: 具體實現
  • 代理: 轉發行為, 轉發之前先實現想要的功能

使用場景: 給類的行為附加上額外的信息


適配器模式

適配器模式: 將一個類的接口轉換成客戶希望的另一個接口, 使得原本由於接口不兼容而不能一起工作的類可以一起工作

實現:

  • 目標 (Target)
    • 這是一個接口或抽象類。
    • 它定義了客戶端期望的接口。
  • 被適配者 (Adaptee)
    • 這是一個已有的類。
    • 它的接口與 Target 接口不兼容。
  • 適配器 (Adapter)
    • 實現 (implements) Target 接口。
    • 內部持有 (has-a) 一個 Adaptee 對象的引用(這就是組合)。
    • 當客戶端調用 Adapter 的方法時,Adapter 內部會將這個調用轉換成對 Adaptee 對象一個或多個方法的調用。
  • 客戶端 (Client)
    • 只與 Target 接口進行交互。

使用場景: 為了複用已有組件的行為, 不需要額外再次實現


中介者模式

中介者模式: 用一個中介對象來封裝(封裝變化)一系統的對象交互。中介者使各對象不需要顯式的相互引用(編譯時依賴->運行時依賴), 從而使其耦合松散(管理變化), 而且可以獨立地改變它們之間的交互

實現:

  1. 中介者 (Mediator)
    • 這是一個接口
    • 它定義了與各個同事 (Colleague) 對象通信的方法。
  2. 具體中介者 (Concrete Mediator)
    • 實現了 Mediator 接口。
    • 知道並維護所有的 Colleague 對象。
    • 它負責實現協調邏輯,接收來自一個 Colleague 的消息,並決定將消息轉發給哪些其他的 Colleagues
  3. 同事 (Colleague)
    • 這通常是一個抽象類接口
    • 它定義了所有同事類都必須遵守的接口。
    • 最關鍵的是,它內部持有一個 Mediator 對象的引用
  4. 具體同事 (Concrete Colleague)
    • 實現了 Colleague 接口。
    • 每個 Colleague 只知道自己的業務邏輯。
    • 當它需要與其他 Colleague 通信時,它不會直接調用其他 Colleague,而是調用它所持有的 Mediator 的方法,由中介者去完成後續的協調。

使用場景: 類和類之間的引用複雜, 使用中介者來隔離類和類的引用


"狀態變化"模式

"狀態變化"模式: 對象的狀態經常變化, 但需要保持高層模块的穩定性


狀態模式

狀態模式: 允許一個對象在其內部狀態改變時改變它的行為, 從而使對象看起來似乎修改了其行為

  • 切換狀態: 不同的狀態對於同一個請求有著不同的行為, 那麼通過切換狀態就可以實現對於同一個請求實現不同的處理

實現:

  1. 上下文 (Context)
    • 這是持有狀態的「主對象」。
    • 它內部維護一個 State 接口的實例,這個實例就是它的當前狀態。
    • 它將所有與狀態相關的行為委託給這個狀態對象。
    • 它通常還提供一個 setter 方法,供狀態對象在需要時改變 Context 的當前狀態。
  2. 狀態 (State)
    • 這是一個接口或抽象類。
    • 它定義了所有具體狀態都必須實現的行為接口。
    • 它通常還會持有一個 Context 的引用,以便能夠讀取 Context 的信息或改變 Context 的狀態。
  3. 具體狀態 (Concrete State)
    • 實現了 State 接口。
    • 每一個具體狀態類都封裝了與 Context 某一個特定狀態相關的行為。
    • 它負責處理來自 Context 的請求,並在適當的時候決定下一個狀態是什麼,然後通過 Context 的 setter 方法來切換 Context 的狀態。

使用場景: 對象的行為依賴於內部狀態, 在運行時根據狀態的改變而改變行為


備忘錄模式

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

  • 序列化代替: 現代通常不使用面向對象來實現保存狀態, 而是使用序列化實現

使用場景: 需要保存類的狀態


"數據結構"模式

"數據結構"模式: 把數據結構封裝到類中, 而不是從用戶實現


組合模式

組合模式: 將對象組合成樹形結構以表示"部分-整體"的層次結構, 使得用戶對單個對象和組合對象的使用具有一致性(穩定)

實現:

  1. 組件 (Component)
    • 這是一個接口抽象類
    • 它為組合中的所有對象(包括葉子和容器)定義了公共接口
    • 它通常還會聲明一些用於管理子組件的方法,如 add(), remove(), getChild()。對於這些方法的實現,有兩種流派:
      • 透明模式 (Transparent):在 Component 接口中聲明所有管理子節點的方法。這樣葉子節點也擁有了這些方法,但通常是空實現或拋出異常。優點是客戶端完全透明,缺點是不夠安全。
      • 安全模式 (Safe):只在 Composite 類中聲明管理子節點的方法。這樣葉子節點就不會有這些無關的方法,更安全,但客戶端需要區分葉子和容器,透明性降低。
  2. 葉子 (Leaf)
    • 實現了 Component 接口。
    • 代表了樹形結構中的終端節點。它沒有子節點
  3. 組合 (Composite)
    • 實現了 Component 接口。
    • 代表了樹形結構中的非終端節點(容器)
    • 它的內部持有一個 Component 對象的集合(std::vector<Component*>)。
    • 它實現 Component 接口的方法時,通常會遍歷其子組件,並將工作委託給它們。
  4. 客戶端 (Client)
    • 通過 Component 接口與組合結構中的對象交互,無需區分葉子和容器。

使用場景: 對象的「部分-整體」層次結構時


迭代器模式

迭代器模式: 提供一種方法順序訪問一個聚合對象的各個元素, 而又不暴露(穩定)該對象的內部表示

  • 不需要了解內部結構": 使用迭代器隔離算法和容器, 而不需要對象的實現是數組、哈希表、紅黑樹等數據結構

實現:

  1. 迭代器 (Iterator)
    • 這是一個接口。
    • 它定義了遍歷元素所需的標準操作,例如:
      • next(): 返回下一個元素,並將迭代器向前移動。
      • hasNext(): 檢查是否還有更多元素。
      • first(): 將迭代器重置到第一個元素(可選)。
      • current(): 返回當前元素(可選)。
  2. 具體迭代器 (Concrete Iterator)
    • 實現了 Iterator 接口。
    • 它負責在一個具體的聚合對象上進行遍歷,並跟蹤當前的位置(例如,數組的下標、鏈表的節點指針)。
    • 它通常會持有一個對其所屬的聚合對象的引用。
  3. 聚合 (Aggregate)
    • 這也是一個接口。
    • 它聲明了一個工廠方法,用於創建一個與之對應的 Iterator 對象,例如 createIterator()。
  4. 具體聚合 (Concrete Aggregate)
    • 實現了 Aggregate 接口。
    • 它持有一個內部元素集合(例如,一個數組或鏈表)。
    • 它實現了 createIterator() 方法,返回一個能夠遍歷其內部結構的 Concrete Iterator 實例。

: C++中有了泛式編程就不需要使用到迭代器模式,

  • 模板是編譯時多態, 它在編譯時就完成了多態的工作, 在運行時基本不會影響性能
  • 迭代器模式使用虛函數實現, 在運行時多態, 會明顯影響性能

使用場景: 類的數據結構會改變, 使用迭代器來隔離類的算法和容器


責任鏈模式

責任鏈模式: 使多個對象都有機會處理請求, 從而避免請求的發送者和接收者之間的耦合關係, 將這些對象連成一條鏈, 并沿著這條鏈傳遞請求, 直到有一個對象處理它為止

實現

  1. 處理者 (Handler)
    • 這通常是一個接口抽象類
    • 它定義了一個處理請求的方法,例如 handleRequest(request)。
    • 最關鍵的是,它內部持有一個指向下一個處理者 (successor) 的引用。
    • 它還會實現一個設置下一個處理者的方法 setSuccessor(handler)。
  2. 具體處理者 (Concrete Handler)
    • 實現了 Handler 接口。
    • 它負責處理它感興趣的請求。
    • 在 handleRequest 方法中,它會先判斷自己能否處理當前請求:
      • 如果能,就處理它,流程結束。
      • 如果不能,就將請求轉發給它的後繼者(successor->handleRequest(request))。
  3. 客戶端 (Client)
    • 負責創建和組裝這條責任鏈。
    • 將請求發送給鏈中的第一個處理者對象。

使用場景: 有多個對象可以處理同一個請求,而具體由哪個對象處理是在運行時動態決定的。


"數據結構"模式

"數據結構"模式: 把數據結構封裝到類中, 而不是從用戶實現


組合模式

組合模式: 將對象組合成樹形結構以表示"部分-整體"的層次結構, 使得用戶對單個對象和組合對象的使用具有一致性(穩定)

實現:

  1. 組件 (Component)
    • 這是一個接口抽象類
    • 它為組合中的所有對象(包括葉子和容器)定義了公共接口
    • 它通常還會聲明一些用於管理子組件的方法,如 add(), remove(), getChild()。對於這些方法的實現,有兩種流派:
      • 透明模式 (Transparent):在 Component 接口中聲明所有管理子節點的方法。這樣葉子節點也擁有了這些方法,但通常是空實現或拋出異常。優點是客戶端完全透明,缺點是不夠安全。
      • 安全模式 (Safe):只在 Composite 類中聲明管理子節點的方法。這樣葉子節點就不會有這些無關的方法,更安全,但客戶端需要區分葉子和容器,透明性降低。
  2. 葉子 (Leaf)
    • 實現了 Component 接口。
    • 代表了樹形結構中的終端節點。它沒有子節點
  3. 組合 (Composite)
    • 實現了 Component 接口。
    • 代表了樹形結構中的非終端節點(容器)
    • 它的內部持有一個 Component 對象的集合(std::vector<Component*>)。
    • 它實現 Component 接口的方法時,通常會遍歷其子組件,並將工作委託給它們。
  4. 客戶端 (Client)
    • 通過 Component 接口與組合結構中的對象交互,無需區分葉子和容器。

使用場景: 對象的「部分-整體」層次結構時


迭代器模式

迭代器模式: 提供一種方法順序訪問一個聚合對象的各個元素, 而又不暴露(穩定)該對象的內部表示

  • 不需要了解內部結構": 使用迭代器隔離算法和容器, 而不需要對象的實現是數組、哈希表、紅黑樹等數據結構

實現:

  1. 迭代器 (Iterator)
    • 這是一個接口。
    • 它定義了遍歷元素所需的標準操作,例如:
      • next(): 返回下一個元素,並將迭代器向前移動。
      • hasNext(): 檢查是否還有更多元素。
      • first(): 將迭代器重置到第一個元素(可選)。
      • current(): 返回當前元素(可選)。
  2. 具體迭代器 (Concrete Iterator)
    • 實現了 Iterator 接口。
    • 它負責在一個具體的聚合對象上進行遍歷,並跟蹤當前的位置(例如,數組的下標、鏈表的節點指針)。
    • 它通常會持有一個對其所屬的聚合對象的引用。
  3. 聚合 (Aggregate)
    • 這也是一個接口。
    • 它聲明了一個工廠方法,用於創建一個與之對應的 Iterator 對象,例如 createIterator()。
  4. 具體聚合 (Concrete Aggregate)
    • 實現了 Aggregate 接口。
    • 它持有一個內部元素集合(例如,一個數組或鏈表)。
    • 它實現了 createIterator() 方法,返回一個能夠遍歷其內部結構的 Concrete Iterator 實例。

: C++中有了泛式編程就不需要使用到迭代器模式,

  • 模板是編譯時多態, 它在編譯時就完成了多態的工作, 在運行時基本不會影響性能
  • 迭代器模式使用虛函數實現, 在運行時多態, 會明顯影響性能

使用場景: 類的數據結構會改變, 使用迭代器來隔離類的算法和容器


責任鏈模式

責任鏈模式: 使多個對象都有機會處理請求, 從而避免請求的發送者和接收者之間的耦合關係, 將這些對象連成一條鏈, 并沿著這條鏈傳遞請求, 直到有一個對象處理它為止

實現

  1. 處理者 (Handler)
    • 這通常是一個接口抽象類
    • 它定義了一個處理請求的方法,例如 handleRequest(request)。
    • 最關鍵的是,它內部持有一個指向下一個處理者 (successor) 的引用。
    • 它還會實現一個設置下一個處理者的方法 setSuccessor(handler)。
  2. 具體處理者 (Concrete Handler)
    • 實現了 Handler 接口。
    • 它負責處理它感興趣的請求。
    • 在 handleRequest 方法中,它會先判斷自己能否處理當前請求:
      • 如果能,就處理它,流程結束。
      • 如果不能,就將請求轉發給它的後繼者(successor->handleRequest(request))。
  3. 客戶端 (Client)
    • 負責創建和組裝這條責任鏈。
    • 將請求發送給鏈中的第一個處理者對象。

使用場景: 有多個對象可以處理同一個請求,而具體由哪個對象處理是在運行時動態決定的。


"行為變化"模式

"行為變化"模式: 實現組件和組件行為的解耦, 適用於在組件的構建過程中, 組件行為的變化經常導致組件本身劇列的變化


命令模式

命令模式: 將一個請求(行為)封裝一個對象, 從而使你可用不同的請求對客戶進行參數化, 對請求排列或記錄請求日志, 以及支持可撤銷的操作

實現:

  1. 命令 (Command)
    • 這是一個接口。
    • 它通常只聲明一個核心的執行方法,如 execute()。
    • 有時也會包含一個 undo() 方法,用於支持撤銷操作。
  2. 具體命令 (Concrete Command)
    • 實現了 Command 接口。
    • 它的內部持有一個接收者 (Receiver) 對象的引用。
    • execute() 方法的實現,就是調用接收者的一個或多個方法來完成具體的業務邏輯。
    • 它還會存儲執行該方法所需的參數。
  3. 接收者 (Receiver)
    • 真正執行業務邏輯的對象。它包含了完成請求所需的具體操作。
    • Receiver 對 Command 的存在一無所知。
  4. 調用者 (Invoker)
    • 持有一個或多個 Command 對象。
    • 它不關心 Command 的具體類型,只知道在適當的時候調用 Command 的 execute() 方法。
    • Invoker 就是觸發命令執行的那個角色。
  5. 客戶端 (Client)
    • 負責創建和組裝所有對象。
    • 它創建一個 Concrete Command 實例,並為其設置一個 Receiver。
    • 然後,它將這個 Command 傳遞給一個 Invoker。

使用場景:

  • 當你需要將請求參數化時,即將操作本身作為參數傳遞。
  • 當你需要支持請求的排隊、日誌記錄或事務操作時。
  • 當你需要實現撤銷 (Undo) 和重做 (Redo) 功能時

訪問器模式

訪問器模式: 一個作用於某對象結構中的各元素的操作。使得可以在不改變(穩定)各元素的類的前提下定義(擴展)作用於這些元素的新操作(變化)

實現:

  1. 訪問者 (Visitor)
    • 這是一個接口
    • 它為對象結構中的每一個具體元素類都聲明了一個 visit 方法。例如 visit(ConcreteElementA), visit(ConcreteElementB)。
  2. 具體訪問者 (Concrete Visitor)
    • 實現了 Visitor 接口。
    • 它封裝了一個特定的演算法或操作。
    • 在遍歷對象結構時,它會存儲計算的中間結果。
  3. 元素 (Element)
    • 這是一個接口。
    • 它聲明了一個核心的 accept(Visitor visitor) 方法,以一個訪問者作為參數。
  4. 具體元素 (Concrete Element)
    • 實現了 Element 接口。
    • accept 方法的實現通常只有一行:visitor.visit(this)。
  5. 對象結構 (Object Structure)
    • 這是一個元素的集合,例如一個列表或一個組合模式的樹。
    • 它通常提供一個高層次的接口,允許客戶端遍歷其所有元素(例如,通過一個迭代器),並對每個元素調用 accept 方法。

使用場景: 不會新增或刪除組件, 而且每個組件經常需要新增或刪除操作


"領域規則"模式

"領域規則"模式: 在特定領域中,某些變化雖然頻繁,但可以抽象為某種規則。這時候,結合特定領域,將問題抽象為語法規則,從而給出在該領域下的一般性解決方案。


"解析器"模式

"解析器"模式: 給定一個語言, 定義它的文法的一種表示, 并定義一種解釋器, 這個解釋器使用該表示來解釋語言中的句子

實現:

  1. AbstractExpression (抽象表達式)
    • 定義一個解釋操作 interpret() 的介面。
    • AST 中所有節點(無論是葉子節點還是非葉子節點)都需要實現這個介面。
  2. TerminalExpression (終端表達式)
    • 實現 AbstractExpression 介面。
    • 代表文法中的「終結符」,也就是最基礎的、不可再分的元素。
    • 例如,在數學運算式 5 + x 中,5 和 x 就是終端表達式。
    • 它的 interpret() 方法通常是直接返回自身的值或從上下文中取值。
  3. NonTerminalExpression (非終端表達式)
    • 實現 AbstractExpression 介面。
    • 代表文法中的「非終結符」,通常是規則或操作,它由一個或多個其他表達式(終端或非終端)組成。
    • 例如,在 5 + x 中,+ (加法操作) 就是非終端表達式,它組合了左邊的 5 和右邊的 x。
    • 它的 interpret() 方法會遞迴地呼叫其子表達式的 interpret() 方法來完成解釋。
  4. Context (上下文)
    • 包含解釋器在解釋時需要的全域資訊或狀態。
    • 例如,在解釋 a + b 時,Context 中會存儲變數 a 和 b 的具體值。
  5. Client (客戶端)
    • 負責構建抽象語法樹,並觸發解釋操作。
    • 例如,客戶端會讀取字串 “5 + x”,然後將其轉換為一個由 NumberExpression, VariableExpression, 和 AddExpression 物件組成的樹狀結構。

使用場景:

  1. 文法簡單:當你需要實現的語言文法非常簡單,且相對穩定,不會頻繁變更。
  2. 效率不是首要考量:解釋器模式通常涉及大量的類和遞迴呼叫,可能導致效能問題。如果效能是瓶頸,可能需要其他技術(如編譯器產生器)。
  3. 需要動態解釋和執行:當一些操作或規則需要被頻繁、動態地執行時,將它們定義為一種語言會非常靈活
http://www.dtcms.com/a/593987.html

相关文章:

  • 有视频接口怎么做网站哪个行业最需要做网站
  • 解锁AI工作流的终极密码:Semantic Kernel Process框架深度技术解析
  • 从0到1:Makefile自动化编译实战全解析
  • 广州网站推广教程中国建设银行网站会员用户名
  • 怎么做分享软件的网站php网站开发框架搭建
  • 网站跟网页的区别jsp做的网页是网站吗
  • 根据docker服务保存日志脚本,时间可选版本
  • 九、神经网络的构建方式详解
  • 第五章 神经网络
  • 网站建设相关的工作鸿顺里网站建设公司
  • 自己做网站卖手机网站建设电话
  • TypeScript 元组
  • LLM - 大模型融合 LangChain 与 OpenRouter 的框架
  • 南宁建企业网站公司办公室装修设计怎么收费
  • 天气形势时间层的选择策略
  • 一站式网站建设多少钱网站怎么会k
  • JAVA实现国密算法SM2/SM3/SM4签名与验签(基于 BouncyCastle)
  • 专门做继电器的网站如何用源码建站
  • ZSAR报错解决
  • CE(Linux的例行性工作)
  • Django中的clean()方法和full_clean()方法
  • 外贸网站怎么注册商城网站开发视频
  • GIT修改用户名
  • 国内最大的摄影网站wordpress大图简约主题
  • hf中transformers库中generate的greedy_search
  • 网站建设优化安徽自己设计logo的软件
  • GetMapping自动截取List<String>字符
  • 以太网环境传感器在物联网系统中的集成与应用前景
  • windows系统启动redis报错
  • 一键部署禅道开源版