設計模式-裝飾器模式(結構型)與責任鏈模式(行為型)對比,以及鏈式設計

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔

文章目錄

  • 前言
  • 1.裝飾器模式
    • 1.1概念
    • 1.2作用
    • 1.3應用場景
    • 1.4特點
    • 1.5類與對象關系
    • 1.6實現
  • 2責任鏈模式
    • 2.1概念
    • 2.2作用
    • 2.3應用場景
    • 2.4特點
    • 2.5類與對象關系
    • 2.6實現
  • 3.對比
  • 總結


前言

裝飾器模式和設計模式同為GoF23中設計模式之一,兩者在結構上有相似之處,本文章用來學習兩個設計模式,并進行對比。


1.裝飾器模式

1.1概念

如果我們想要為一個已經寫好的類增加新功能,在不修改該類源碼的情況下,我們有以下選擇:

  • 創建該類的子類,并用該子類調用父類方法,并額外添加其他功能
  • 創建一個新的類,引用已有類的對象,調用原有方法并添加其他功能

這里第二種實現思路就是我們現在說的裝飾器模式。

1.2作用

為一個已有的類增加新的功能。

1.3應用場景

  • 需要動態地給對象添加職責時:當你需要給某個對象添加職責,但又不想修改其類定義時,可以使用裝飾器模式。
  • 需要靈活組合多個職責時:當你有多個職責需要組合,并且這些職責的排列組合可能會變化時,裝飾器模式是一個很好的選擇。
  • 需要保持類的單一職責原則時:當你想保持類的單一職責原則,但又需要給類添加額外的職責時,可以使用裝飾器模式將這些職責分離到裝飾器

1.4特點

  • 動態擴展:裝飾器模式能夠在運行時動態地給對象添加職責,而無需修改類的定義。
  • 靈活性:通過組合的方式而不是繼承來擴展功能,這使得裝飾器模式比繼承更加靈活。
  • 遵循開閉原則:裝飾器模式可以在不修改現有代碼的情況下添加新的功能,符合開閉原則(對擴展開放,對修改關閉)。
  • 裝飾器與被裝飾對象擁有相同的接口:這使得裝飾器可以透明地替代被裝飾對象

1.5類與對象關系

在這里插入圖片描述

  • 組件接口:對應上圖Component,用來規定被裝飾對象和裝飾器應該有哪些功能(或者說原組件中哪些功能是可以裝飾的)
  • 組件類:對應上圖ConcreteComponent,是被裝飾對象
  • 抽象裝飾器:對應上圖Decorator,是一個接口,因為我們會有多個不同的具體裝飾器,所以需要使用一個抽象裝飾器接口來指定具體裝飾器應該有哪些功能
  • 具體裝飾器:是我們真正的額外功能編寫的地方,因為實現了抽象裝飾器所以擁有與被裝飾對象相同但更強大的功能,可以在使用時進行替換。

1.6實現

// 定義一個接口,規定哪些方法可以被裝飾
interface Component {void operation();
}// 具體組件類,實現了Component接口
class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 抽象裝飾器類,持有一個Component對象,并實現了Component接口
abstract class Decorator implements Component {// 該對象存儲原對象或者被其他裝飾器裝飾過的對象// 因為可以是其他裝飾器裝飾過的對象,所以才實現裝飾器的疊加,是動態添加功能的關鍵protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}// 具體裝飾器類A,增加了額外的行為
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorA added behavior");}
}// 具體裝飾器類B,增加了額外的行為
class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {addedBehavior();super.operation();}private void addedBehavior() {System.out.println("ConcreteDecoratorB added behavior");}
}// 客戶端代碼
public class DecoratorPatternDemo {public static void main(String[] args) {Component component = new ConcreteComponent();// 使用裝飾器A裝飾Component decoratorA = new ConcreteDecoratorA(component);// 使用裝飾器B裝飾裝飾器AComponent decoratorB = new ConcreteDecoratorB(decoratorA);// 執行操作,將展示所有組件和裝飾器的行為decoratorB.operation();}
}

2責任鏈模式

2.1概念

責任鏈模式是一種行為設計模式,它允許你將請求沿著處理者鏈進行傳遞。每個處理者可以對請求進行處理,或者將請求傳遞給鏈中的下一個處理者。這使得你可以在不明確具體接收者的情況下,向多個對象發送請求。

2.2作用

  • 解耦請求與處理:請求者只要向鏈頭發送一次請求,而不用關心具體由誰處理。
  • 可以動態管理處理類:可以按需添加或刪除處理類。

2.3應用場景

  • 多個對象有機會處理請求:當請求可以在多個對象之間傳遞,并且每個對象都有可能處理它時。
  • 請求處理順序可變:當請求的處理順序不固定,或者你想在不修改代碼的情況下改變處理順序時。
  • 解耦請求發送者和處理者:當你想解耦請求發送者和處理者之間的依賴關系時。

2.4特點

  • 鏈式傳遞:請求在多個處理者之間傳遞,直到有一個處理者處理它或鏈結束。
  • 解耦請求發送者和接收者:發送者不需要知道哪個具體的處理者會處理請求,它只需要將請求發送到鏈的頭部即可。
  • 增強靈活性:你可以通過動態地添加或刪除處理者來改變鏈的結構,從而改變請求的處理流程。

2.5類與對象關系

在這里插入圖片描述

責任鏈模式中我們有以下角色:

  • 抽象處理者(Handler)角色:聲明“處理”方法,以及一個“設置下一處理器”的方法
  • 具體處理者(Concrete Handler)角色:實現了抽象處理者接口,并包含處理請求的邏輯。如果它不能處理請求,它會將請求傳遞給鏈中的下一個處理者。

2.6實現

// 抽象處理者接口
abstract class Handler {protected Handler nextHandler;// 設置下一個處理者public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}// 處理請求的方法,由具體處理者實現public abstract void handleRequest(String request);
}// 具體處理者類A
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("ConcreteHandlerA handled request: " + request);} else {if (nextHandler != null) {nextHandler.handleRequest(request);}}}
}// 具體處理者類B
class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("ConcreteHandlerB handled request: " + request);} else {if (nextHandler != null) {nextHandler.handleRequest(request);}}}
}// 客戶端代碼
public class ChainOfResponsibilityDemo {public static void main(String[] args) {// 創建處理者對象Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();// 構建處理者鏈handlerA.setNextHandler(handlerB);// 創建并發送請求String[] requests = {"A", "B", "C"};for (String request : requests) {handlerA.handleRequest(request); // 請求從handlerA開始傳遞}}
}

3.對比

  1. 首先,鏈式設計最重要的一點是——一個節點中要存儲相鄰節點的信息,這一點在上述兩種設計模式中都有體現。這里要先清楚各自具體存儲的是什么。
  • 裝飾器模式存儲的是原組件或被修飾過的組件,這說明在該種模式下各個裝飾器的作用是可以疊加的
  • 責任鏈模式存儲的是下一個處理節點,這里各個處理器效果并不會疊加
  1. 其次,各個節點應該有同樣的任務。這兩種模式中不論是各個裝飾器,還是各個處理器,其實都有同樣的任務。但是兩個模式在具體實現時有區別,這也是裝飾器模式可疊加而責任鏈模式不可疊加的原因。
  • 裝飾器中的方法邏輯是——上一節點處理邏輯"及"本節點處理邏輯
  • 責任鏈中的方法邏輯是——本節點處理邏輯"或"下節點處理邏輯

總結

本文章比較了裝飾器模式和責任鏈模式,因為兩者在結構上十分相似都使用了鏈式設計,所以容易混淆,這里需要重點理解兩者在處理方法中的實現邏輯的不同,裝飾器是"且",責任鏈是"或"。

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

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

相關文章

交叉熵損失函數(Cross-Entropy Loss)

原理 交叉熵損失函數是深度學習中分類問題常用的損失函數,特別適用于多分類問題。它通過度量預測分布與真實分布之間的差異,來衡量模型輸出的準確性。 交叉熵的數學公式 交叉熵的定義如下: C r o s s E n t r o y L o s s ? ∑ i 1 N …

操作系統:死鎖與饑餓

目錄 死鎖概念 饑餓與餓死概念 饑餓和死鎖對比 死鎖類型 死鎖條件(Coffman條件) 死鎖恢復方法 死鎖避免 安全狀態與安全進程序列: 銀行家算法: 死鎖檢測時機(了解): 死鎖檢測 死鎖案…

Prisoner’s Dilemma

囚徒困境博弈論解析 什么是囚徒困境? 囚徒困境(Prisoner’s Dilemma)是博弈論中的一個經典模型,用來分析兩名玩家在非合作環境下的決策行為。 其核心在于玩家既可以選擇合作也可以選擇背叛,而最終的結果取決于雙方的…

RPO: Read-only Prompt Optimization for Vision-Language Few-shot Learning

文章匯總 想解決的問題對CoOp的改進CoCoOp盡管提升了性能,但卻增加了方差(模型的準確率波動性較大)。 模型的框架一眼看去,跟maple很像(maple跟這篇文章都是2023年發表的),但maple的視覺提示是由文本提示經過全連接轉換而來的,而這里是文本提示和視覺提示是獨立的。另外m…

『MySQL 實戰 45 講』24 - MySQL是怎么保證主備一致的?

MySQL是怎么保證主備一致的? MySQL 主備的基本原理 基本的主備切換流程 狀態 1:客戶端的讀寫都直接訪問節點 A,而節點 B 是 A 的備庫狀態 2:切換時,讀寫訪問的都是節點 B,而節點 A 是 B 的備庫注意&…

自薦一部IT方案架構師回憶錄

作者本人畢業于一個不知名大專院校,所讀專業計算機科學技術。2009年開始IT職業生涯,至今工作15年。擅長TSQL/Shell/linux等技術,曾經就職于超萬人大型集團、國內頂級云廠商、央國企公司。參與過運營商大數據平臺、大型智慧城市ICT、云計算、人…

python數據分析之爬蟲基礎:selenium詳細講解

目錄 1、selenium介紹 2、selenium的作用: 3、配置瀏覽器驅動環境及selenium安裝 4、selenium基本語法 4.1、selenium元素的定位 4.2、selenium元素的信息 4.3、selenium元素的交互 5、Phantomjs介紹 6、chrome handless模式 1、selenium介紹 (1…

【數據結構——查找】順序查找(頭歌實踐教學平臺習題)【合集】

目錄😋 任務描述 相關知識 測試說明 我的通關代碼: 測試結果: 任務描述 本關任務:實現順序查找的算法。 相關知識 為了完成本關任務,你需要掌握:1.根據輸入數據建立順序表,2.順序表的輸出,…

光伏電站建設成本利潤估算

?截至2024年9月底,全國光伏發電裝機容量達到7.7億千瓦,同比增長48.4%。其中集中式光伏4.3億千瓦,分布式光伏3.4億千瓦。2024年前三季度,全國光伏發電量6359億千瓦時,同比增長45.5%。全國光伏發電利用率97.2%,同比下降1.1個百分點.早在今年2月份,中國光伏行業協會名譽理…

create-react-app react19 搭建項目報錯

報錯截圖 此時運行會報錯: 解決方法: 1.根據提示安裝依賴法 執行npm i web-vitals然后重新允許 2.刪除文件法 在index.js中刪除對報錯文件的引入,刪除報錯文件

scala的集合性能2

可變集合\n可變集合允許在原地修改數據,適合需要頻繁更新的場景。Scala 的可變集合包括 ArrayBuffer、HashSet和HashMap。 1. ArrayBuffer\nArrayBuffer 是一個可變的動態數組,提供高效的隨機訪問和添加操作。 import scala.collection.mutable.ArrayB…

【Ubuntu】腳本自動化控制終端填充

1.sh腳本文件控制終端寫入命令 在SLAM算法中,每次啟動vins都需要起很多終端,盡管使用了超級終端Terminator可以終端內劃分看起來更加便捷,但是每次起算法的命令還是要自己輸入,已經被麻煩了兩年了,今天突然想寫寫一個…

【自學】Vues基礎

學習目錄 Vues基礎本地應用網絡應用綜合應用 工具的準備 我個人比較喜歡使用HTMLDROWNER,學習資料推薦使用VC,僅供選擇吧 前置知識 HTMLCSSJSAJAX:這個是學習資料博主推薦的 個人感覺認真學好HTMLCSSJS理解vues基礎很容易上手 官方網址…

Scratch 消滅字母小游戲

背景 最近嘗試一邊自學Scratch,一邊嘗試教給小孩,看他打字時在鍵盤上亂打一氣,想起來自己小時候玩過的學習機打字母游戲,就想給他下載一個。結果網上看到的代碼,要么質量太差(有26個字母就要寫 26 個判斷&…

python調用matlab函數(內置 + 自定義) —— 安裝matlab.engine

文章目錄 一、簡介二、安裝matlab.engine2.1、基于 CMD 安裝2.2、基于 MATLAB 安裝(不建議) 三、python調用matlab函數(內置 自定義) 一、簡介 matlab.engine(MATLAB Engine API for Python):…

pytroch環境安裝-pycharm

環境介紹 安裝pycharm 官網下載即可,我這里已經安裝,就不演示了 安裝anaconda 【官網鏈接】點擊下載 注意這一步選擇just me 這一步全部勾上 打開 anaconda Prompt 輸入conda create -n pytorch python3.8 命令解釋:創建一個叫pytorch&…

Photoshop提示錯誤彈窗dll缺失是什么原因?要怎么解決?

Photoshop提示錯誤彈窗“DLL缺失”:原因分析與解決方案 在創意設計與圖像處理領域,Photoshop無疑是眾多專業人士和愛好者的首選工具。然而,在使用Photoshop的過程中,有時會遇到一些令人頭疼的問題,比如突然彈出的錯誤…

自己總結:selenium高階知識

全篇大概10000字(含代碼),建議閱讀時間30min 一、等待機制 如果有一些內容是通過Ajax加載的內容,那就需要等待內容加載完畢才能進行下一步操作。 為了避免人為操作等待,會遇到的問題, selenium將等待轉換…

上海亞商投顧:創業板指震蕩調整 機器人概念股再度爆發

上海亞商投顧前言:無懼大盤漲跌,解密龍虎榜資金,跟蹤一線游資和機構資金動向,識別短期熱點和強勢個股。 一.市場情緒 滬指昨日沖高回落,深成指、創業板指盤中跌超1%,尾盤跌幅有所收窄。機器人概念股逆勢爆…

(Linux)CentOS7離線安裝MinIO(超詳細)

目錄 前言1. 下載2. 安裝VMware3. 安裝CentOS4. 離線安裝MinIO4.1. ssh工具連接CentOS4.2. 上傳MinIO離線包4.2.1 創建data目錄4.2.2 上傳RPM包到data目錄4.2.3 安裝RPM包4.2.4 創建MinIO數據目錄4.2.5 配置 MinIO 服務4.2.6 啟動 MinIO4.2.7 開放端口 4.2.8 訪問MinIO 創作不易…