責任鏈模式 (Chain of Responsibility Pattern)

定義

責任鏈模式是一種行為型設計模式,用于在對象間建立一條處理請求的鏈。它允許多個對象有機會處理請求,從而減少請求的發送者和接收者之間的耦合。在責任鏈模式中,每個接收者包含對另一個接收者的引用,形成一條鏈。如果一個對象不能處理請求,它會將請求傳遞給鏈中的下一個對象,直至鏈的末端。

責任鏈模式由多個處理器(或接收者)組成,每個處理器決定自己是否處理請求或將其傳遞給鏈上的下一個處理器。這種模式實現了發送者和接收者之間的解耦,同時允許動態地調整鏈中的處理器。

責任鏈模式主要包含以下兩個角色:

  1. 處理器(Handler)
    • 定義了處理請求的接口或抽象類,并通常持有對下一個處理器的引用。在其子類中,它可以選擇處理請求或將請求傳遞給鏈上的下一個對象。
  2. 具體處理器(Concrete Handler)
    • 實現處理器接口的具體類。每個具體處理器決定它是否要處理請求,如果不處理,則將請求傳遞給鏈中的下一個對象。
解決的問題
  • 請求的發送者和接收者解耦
    • 在沒有責任鏈模式的情況下,請求的發送者需要知道哪個接收者能夠處理該請求,并直接調用相應的處理方法。責任鏈模式使得請求的發送者不需要直接與具體的接收者交互,從而解耦了發送者和接收者。
  • 動態處理請求
    • 責任鏈模式允許動態地重新組織和分配責任鏈上的處理者。這意味著可以在運行時改變請求的處理順序或者增加新的處理者。
  • 簡化對象間的連接
    • 通過責任鏈,可以減少對象間復雜的條件語句。在責任鏈模式中,請求沿著鏈傳遞,直到被處理。這避免了顯式的多重條件判斷。
  • 增加處理者的靈活性
    • 責任鏈模式讓每個處理者都有機會處理請求。處理者可以決定是否處理請求,或者將請求傳遞給鏈上的下一個對象。
  • 分布式責任
    • 責任鏈模式允許多個對象處理請求,而不是只有一個對象負責所有的情況。這種分布式責任有助于代碼的復用和擴展。
使用場景
  • 多個對象可以處理同一個請求,但具體的處理者在運行時才確定
    • 當一個請求可能由多個不同的對象處理,但是具體由哪個對象處理在運行時才決定時,責任鏈模式是理想的解決方案。
  • 請求的發送者不需要知道是誰處理了請求
    • 如果請求的發送者不需要知道請求最終由哪個對象處理,責任鏈模式可以將請求的發送和處理解耦。
  • 動態指定一組對象處理請求
    • 當需要動態地指定一系列對象來處理請求時,責任鏈模式提供了一種靈活的方法來組織這些對象。
  • 實現不同方式的請求處理
    • 在有多種處理方式,并且希望根據請求的類型或條件以不同的方式處理時,責任鏈模式能夠提供足夠的靈活性。
示例代碼1-日志處理器
// 抽象處理器類
public abstract class Logger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;protected Logger nextLogger;public void setNextLogger(Logger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(int level, String message) {if (this.level <= level) {write(message);}if (nextLogger != null) {nextLogger.logMessage(level, message);}}abstract protected void write(String message);
}// 具體處理器實現
class ConsoleLogger extends Logger {public ConsoleLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {        System.out.println("Standard Console::Logger: " + message);}
}// 客戶端使用責任鏈
public class ChainPatternDemo {private static Logger getChainOfLoggers() {Logger errorLogger = new ErrorLogger(Logger.ERROR);Logger fileLogger = new FileLogger(Logger.DEBUG);Logger consoleLogger = new ConsoleLogger(Logger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;}public static void main(String[] args) {Logger loggerChain = getChainOfLoggers();loggerChain.logMessage(Logger.INFO, "This is an information.");loggerChain.logMessage(Logger.DEBUG, "This is a debug level information.");loggerChain.logMessage(Logger.ERROR, "This is an error information.");}
}
示例代碼2-審批流程
// 抽象處理器
abstract class Approver {protected Approver successor;public void setSuccessor(Approver successor) {this.successor = successor;}public abstract void processRequest(PurchaseRequest request);
}// 具體處理器:經理
class Manager extends Approver {public void processRequest(PurchaseRequest request) {if (request.getAmount() < 1000) {System.out.println("Manager will approve the request of " + request.getAmount());} else if (successor != null) {successor.processRequest(request);}}
}// 具體處理器:總監
class Director extends Approver {public void processRequest(PurchaseRequest request) {if (request.getAmount() < 5000) {System.out.println("Director will approve the request of " + request.getAmount());} else if (successor != null) {successor.processRequest(request);}}
}// 具體處理器:CEO
class CEO extends Approver {public void processRequest(PurchaseRequest request) {if (request.getAmount() < 10000) {System.out.println("CEO will approve the request of " + request.getAmount());} else {System.out.println("Request of " + request.getAmount() + " needs a board meeting!");}}
}// 請求類
class PurchaseRequest {private double amount;public PurchaseRequest(double amount) {this.amount = amount;}public double getAmount() {return amount;}
}// 客戶端代碼
public class ChainOfResponsibilityDemo {public static void main(String[] args) {Approver manager = new Manager();Approver director = new Director();Approver ceo = new CEO();manager.setSuccessor(director);director.setSuccessor(ceo);manager.processRequest(new PurchaseRequest(500));manager.processRequest(new PurchaseRequest(1500));manager.processRequest(new PurchaseRequest(5500));}
}
主要符合的設計原則
  • 開閉原則(Open-Closed Principle)
    • 責任鏈模式允許在不修改現有代碼的情況下添加新的處理器。你可以添加新的處理類來擴展系統的功能,而無需修改現有的處理鏈或客戶端代碼。因此,系統對擴展是開放的,但對修改是封閉的。
  • 單一職責原則(Single Responsibility Principle)
    • 在責任鏈模式中,每個處理器只負責處理特定類型的請求。這符合單一職責原則,因為每個處理器類只有一個理由發生變化——處理其特定的請求。
  • 里氏替換原則(Liskov Substitution Principle)
    • 責任鏈中的處理器通常遵循相同的接口。這意味著處理器的任何子類都可以替換其父類,而不影響系統的行為。
在JDK中的應用
  • java.util.logging.Logger
    • java.util.logging 包中,Logger 類使用責任鏈模式。日志消息可以在一個日志處理鏈中傳遞,每個處理器(如 ConsoleHandler, FileHandler)決定是否處理日志消息,并將消息傳遞到鏈中的下一個處理器。
  • Java Servlet Filters
    • 在Java Servlet API中,過濾器(Filter)使用責任鏈模式。請求和響應在多個過濾器之間傳遞,每個過濾器可以獨立地處理請求或響應,或將其傳遞給鏈中的下一個過濾器。
  • javax.servlet.FilterChain
    • FilterChain 是Servlet API的一部分,它允許多個過濾器按順序處理HTTP請求和響應。每個過濾器在鏈中都有機會處理請求和響應,或將其傳遞給鏈上的下一個過濾器。
在Spring中的應用
  • Spring Security的過濾器鏈
    • 在Spring Security中,安全過濾器鏈是責任鏈模式的一個顯著例子。請求通過一系列的安全過濾器,每個過濾器執行特定的安全檢查(如認證、授權等)。這些過濾器可以自定義和配置,形成一個處理安全的責任鏈。
  • Spring Web的攔截器
    • 在Spring MVC中,攔截器(Interceptor)提供了一種在處理HTTP請求時插入自定義邏輯的機制。攔截器可以形成一個攔截器鏈,每個攔截器按順序執行,處理請求或響應,或將控制權傳遞給鏈中的下一個攔截器。
  • Spring AOP的通知鏈
    • 在Spring的面向切面編程(AOP)中,通知(Advice)可以被看作是責任鏈的一部分。不同的通知(如前置通知、后置通知、環繞通知等)可以按順序應用于方法調用,形成一個通知鏈。

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

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

相關文章

tcp和 udp區別

相同點&#xff1a;都是傳輸層協議 不同點 是否面向連接 tcp:面向連接 三次握手&#xff0c;四次揮手端對端連接全雙工通信&#xff08;允許雙端同時收發數據&#xff09; udp:無連接 無三次握手&#xff0c;四次揮手支持一對一,一對多&#xff0c;多對多 數據傳輸方式 …

Linux平臺下使用.NET Core訪問Access數據庫

運行環境 操作系統&#xff1a;Ubuntu 22.04.3 LTS (Jammy)開發工具&#xff1a;Visual Studio 2022 (17.8.0)運行時版本&#xff1a;.NET Runtime 8.0依賴庫&#xff1a;unixodbc、mdbtools、odbc-mdbtools 依賴庫安裝 apt-get update sudo apt-get install unixodbc mdbto…

部署項目時常用的 Linux 命令

目錄 1 前言2 SSH登錄命令3 SCP傳輸命令4 CP拷貝命令5 MV移動命令6 TAR解壓命令7 DU查看文件夾/文件大小8 TAIL查看日志9 NOHUP后臺運行10 結語 1 前言 在應用部署過程中&#xff0c;Linux命令是必不可少的工具。它們能夠幫助我們管理文件、連接服務器、拷貝文件、查看日志以及…

vite項目配置vite.config.ts在打包過程中去除日志

在生產環境上&#xff0c;務必要將日志清除干凈&#xff0c;其因有二&#xff0c;在webgis系統中&#xff0c;有很多幾何數據&#xff0c;體積大、數量多&#xff0c;很容易引起系統卡頓&#xff1b;清除log后&#xff0c;系統看著舒服&#xff0c;協同開發有很多無聊的日志&am…

生日禮物——華為機考真題

題目描述 小牛的孩子生日快要到了&#xff0c;他打算給孩子買蛋糕和小禮物&#xff0c;蛋糕和小禮物各買一個&#xff0c; 他的預算不超過x元。蛋糕 Cake 和小禮物 gift 都有多種價位的可供選擇。 請返回小牛共有多少種購買方案。 輸入描述 第一行表示 Cake的單價, 以逗號分隔 …

字符串:leetcode1410. HTML 實體解析器

1410. HTML 實體解析器 「HTML 實體解析器」 是一種特殊的解析器&#xff0c;它將 HTML 代碼作為輸入&#xff0c;并用字符本身替換掉所有這些特殊的字符實體。 HTML 里這些特殊字符和它們對應的字符實體包括&#xff1a; 雙引號&#xff1a;字符實體為 &quot; &#xff…

一款非常優秀的項目管理工具:進度貓(推薦)

在項目管理中&#xff0c;一個好的工具可以極大地提高效率。 進度貓是一款非常優秀的項目管理工具。它具有非常強大的功能&#xff0c;可以幫助團隊更好地管理項目進度。 通過可視化的方式&#xff0c;將項目進度、任務分配、需求變更等全面呈現給團隊成員&#xff0c;讓團隊…

5.過濾敏感詞 + 發布帖子 + 帖子詳情

目錄 1.過濾敏感詞 1.1 定義前綴樹 1.2 根據敏感詞,初始化前綴樹 1.3 編寫過濾敏感詞方法

需求分析BSA法

&#x1f449;BSA法&#xff08;Basic–Satisfier–Attractor&#xff09;是對客戶需求進行優先級劃分的需求分析方法。該模型體現了需求滿足度和客戶滿意度之間的非線性關系。BSA法將客戶需求分為3種類型&#xff0c;分別是基本型需求、滿意型需求和興奮型需求。下面將對每種需…

ABB機 器 人 操 作 培 訓

目 錄 1 培訓手冊介紹 ---------------------------------------------2 2 系統安全與環境保護 ---------------------------------------------3 3 機器人綜述 ---------------------------------------------5 4 機器人示教 --------------------------------------------12…

哲學家就餐問題(java全代碼)

題目 有N個哲學家圍坐在一張圓桌旁&#xff0c;桌上只有N把叉子&#xff0c;每對哲學家中間各有一把。 哲學家的兩種行為&#xff1a; 一、思考 二、吃意大利面 哲學家只能拿起手邊左邊或右邊的叉子 吃飯需要兩把叉子 正確地模仿哲學家的行為 方法一 一次只允許四個人…

FSCTF2023-Reverse方向題解WP。學習貼

文章目錄 [FSCTF 2023]signin[FSCTF 2023]MINE SWEEPER[FSCTF 2023]Xor[FSCTF 2023]EZRC4[FSCTF 2023]ez_pycxor[FSCTF 2023]Tea_apk[FSCTF 2023]ezcode[FSCTF 2023]ezbroke[FSCTF 2023]rrrrust!!![FSCTF2023]ezrev&#xff08;未解決&#xff09; [FSCTF 2023]signin UPX殼&am…

redis-cluster集群模式

Redis-cluster集群 1 Redis3.0引入的分布式存儲方案 2集群由多個node節點組成,redis數據分布在節點之中,在集群之中分為主節點和從節點3集群模式當中,主從一一對應,數據寫入和讀取與主從模式一樣&#xff0c;主負責寫&#xff0c;從只能讀4集群模式自帶哨兵模式&#xff0c;可…

自然資源土地管理法律法規知識競賽這么辦才高端

近些年&#xff0c;全國各地自然資源廳舉辦了土地管理法律法規知識競賽&#xff0c;從我公司承辦的這些賽事來看&#xff0c;傳統的必答題、搶答題、風險題的方式已無法激起現場比賽氣氛&#xff0c;需要更加復雜有趣的環節設置及高端競賽軟件及其配套設備加持才可以讓知識競賽…

Eigen::Matrix 轉 std::vector 親測ok!

std::vector<double> data;for (int kk 0; kk < 24; kk) {data.push_back(kk);}int n 24 / 3;typedef Eigen::Matrix<double, 3, Eigen::Dynamic> MatrixXd;//vector 轉 matrixEigen::Map<Eigen::MatrixXd> result(data.data(), 3, n);//matrix 轉 vect…

什么是交易量價差分析法?anzo Capital一分鐘講明白

交易量價差分析法是一種深入的市場分析方法&#xff0c;它主要探討了價格、價差和交易量之間的相互關系。在此過程中&#xff0c;交易量主要揭示了市場上的交易活動情況&#xff0c;而價差則反映了這些交易的價格變動。 為了更準確地理解這種關系&#xff0c;定義了交易量價差…

21. Spring擴展點之推斷構造方法

簡介 spring自己本身有推斷構造方法的邏輯&#xff0c;但同時也提供了擴展&#xff0c;SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors&#xff0c;實現該方法就可以自己定制獲取哪個構造器的邏輯&#xff0c;該擴展點spring有一個默認的實現Autow…

單元測試-java.lang.NullPointerException

報錯信息 java.lang.NullPointerException 空指針異常 空對象引用 來源 對Controller層進行單元測試&#xff0c;解決完Spring上下文報錯后繼續報錯。 解決 在測試方法執行前要為字段完成對象的注入&#xff0c;否則就報空指針異常。 測試例子 public class SysUserContr…

前端css粘性布局,頂部吸附效果(position: sticky)

sticky屬性設置 /* 設置粘性布局 */ position: sticky; /* 拖動滾動條&#xff0c;當前元素超出文檔0的位置時&#xff0c;觸發定位效果&#xff08;同級元素位置不會受影響&#xff09; */ top: 0;頁面初始效果 設置前&#xff08;滾動頁面時&#xff0c;標簽欄隨頁面滾動&a…

【深度學習】六大聚類算法快速了解

在機器學習中&#xff0c;無監督學習一直是我們追求的方向&#xff0c;而其中的聚類算法更是發現隱藏數據結構與知識的有效手段。目前如谷歌新聞等很多應用都將聚類算法作為主要的實現手段&#xff0c;它們能利用大量的未標注數據構建強大的主題聚類。本文從最基礎的 K 均值聚類…