設計模式精講 Day 13:責任鏈模式(Chain of Responsibility Pattern)

【設計模式精講 Day 13】責任鏈模式(Chain of Responsibility Pattern)


文章內容

在“設計模式精講”系列的第13天,我們將深入講解責任鏈模式(Chain of Responsibility Pattern)。這是一種行為型設計模式,它通過將請求的發送者和接收者解耦,使得多個對象都有機會處理請求,從而避免了請求的發送者與接收者之間的緊耦合。

責任鏈模式的核心思想是:將請求的處理過程組織成一個鏈式結構,每個處理節點可以決定是否處理該請求或將其傳遞給下一個節點。這種模式非常適合處理需要多個條件判斷、權限校驗、審批流程等場景,能夠有效提升系統的靈活性和可擴展性。

本篇文章將從理論到實踐全面解析責任鏈模式,包括其定義、結構、適用場景、實現方式、工作原理、優缺點分析,并結合真實項目案例進行深入探討。同時,我們還將展示如何在Java中實現責任鏈模式,并討論其在Java標準庫及主流框架中的應用實例。


模式定義

責任鏈模式(Chain of Responsibility Pattern) 是一種行為型設計模式,它允許你將請求的發送者與接收者解耦。請求通過一系列處理對象進行傳遞,直到某個對象決定處理它為止。每個處理對象都包含對下一個處理對象的引用,形成一條鏈。

該模式的核心思想是:

  • 解耦請求的發送者與接收者
  • 允許多個對象有機會處理請求
  • 動態構建處理鏈

模式結構

責任鏈模式由以下幾個關鍵角色組成:

角色說明
抽象處理者(Handler)定義處理請求的接口,通常包含一個指向下一個處理者的引用。
具體處理者(Concrete Handler)實現具體的處理邏輯,決定是否處理請求或將其傳遞給下一個處理者。
客戶端(Client)創建處理鏈并發起請求。

類圖結構描述

+----------------+
|   Handler      |
+----------------+
| - next: Handler|
+----------------+
| + setNext()    |
| + handleRequest()|
+----------------+▲│
+----------------+
| ConcreteHandlerA|
+----------------+
| + handleRequest()|
+----------------+▲│
+----------------+
| ConcreteHandlerB|
+----------------+
| + handleRequest()|
+----------------+

每個具體處理者繼承自抽象處理者,維護一個對下一個處理者的引用。當當前處理者無法處理請求時,它會將請求傳遞給下一個處理者。


適用場景

責任鏈模式適用于以下典型場景:

場景說明
多級審批流程如請假審批、報銷申請、合同簽署等,不同層級的審批人按順序處理請求
權限驗證在系統中對用戶權限進行逐級驗證,如登錄、訪問控制、操作權限等
日志記錄不同級別的日志信息被不同處理器處理,如調試日志、錯誤日志、審計日志
過濾器鏈Web開發中的過濾器(Filter)、攔截器(Interceptor)等
事件處理GUI事件、消息隊列中的消息處理等

這些場景中,請求的處理可能涉及多個步驟,且處理邏輯具有一定的優先級或順序性,此時使用責任鏈模式能有效提高系統的可維護性和可擴展性。


實現方式

下面是一個完整的 Java 示例,演示責任鏈模式的基本實現。

抽象處理者(Handler)
// 抽象處理者
public abstract class Handler {protected Handler next;public void setNext(Handler next) {this.next = next;}// 處理請求的方法public void handleRequest(Request request) {if (canHandle(request)) {doHandle(request);} else if (next != null) {next.handleRequest(request);} else {System.out.println("No handler can process the request.");}}// 判斷是否可以處理該請求protected abstract boolean canHandle(Request request);// 具體處理邏輯protected abstract void doHandle(Request request);
}
具體處理者(Concrete Handler)
// 具體處理者1:處理普通請求
public class ConcreteHandlerA extends Handler {@Overrideprotected boolean canHandle(Request request) {return request.getType() == RequestType.NORMAL;}@Overrideprotected void doHandle(Request request) {System.out.println("ConcreteHandlerA handled the request: " + request.getMessage());}
}// 具體處理者2:處理緊急請求
public class ConcreteHandlerB extends Handler {@Overrideprotected boolean canHandle(Request request) {return request.getType() == RequestType.EMERGENCY;}@Overrideprotected void doHandle(Request request) {System.out.println("ConcreteHandlerB handled the request: " + request.getMessage());}
}
請求類(Request)
// 請求類
public class Request {private RequestType type;private String message;public Request(RequestType type, String message) {this.type = type;this.message = message;}public RequestType getType() {return type;}public String getMessage() {return message;}
}
枚舉類型(RequestType)
// 請求類型枚舉
public enum RequestType {NORMAL,EMERGENCY
}
客戶端調用示例
public class Client {public static void main(String[] args) {// 創建處理鏈Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNext(handlerB);// 發起請求Request request1 = new Request(RequestType.NORMAL, "This is a normal request.");Request request2 = new Request(RequestType.EMERGENCY, "This is an emergency request.");handlerA.handleRequest(request1); // 會被ConcreteHandlerA處理handlerA.handleRequest(request2); // 會被ConcreteHandlerB處理}
}
單元測試代碼(JUnit 5)
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;public class ChainOfResponsibilityTest {@Testpublic void testChainOfResponsibility() {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNext(handlerB);Request request1 = new Request(RequestType.NORMAL, "Normal request");Request request2 = new Request(RequestType.EMERGENCY, "Emergency request");handlerA.handleRequest(request1);handlerA.handleRequest(request2);}
}

工作原理

責任鏈模式通過鏈式結構來傳遞請求,每個處理者都擁有對下一個處理者的引用。當請求到達鏈頭時,第一個處理者嘗試處理,如果不能處理,則將請求傳遞給下一個處理者,依此類推。

這種方式的優點在于:

  • 請求的發送者不需要知道具體由哪個處理者處理,只需將請求發送到鏈頭即可。
  • 處理鏈可以動態構建和修改,無需修改請求發送者的代碼。
  • 提高了系統的可擴展性,新增處理者只需加入鏈中,不影響現有邏輯。

優缺點分析

優點缺點
解耦請求的發送者與接收者鏈式結構可能導致調試困難
提高系統的靈活性和可擴展性請求可能未被任何處理者處理,需注意邊界情況
支持動態配置處理鏈若鏈過長,可能影響性能
易于添加新的處理者需要合理設計處理順序,否則可能造成邏輯混亂

案例分析:企業審批系統

假設我們正在開發一個企業內部的審批系統,用于處理員工的請假申請。根據請假天數的不同,審批流程也不同:

  • 1天以內:部門經理審批
  • 2~5天:部門經理 + 人事部審批
  • 5天以上:部門經理 + 人事部 + 總經理審批

在這種情況下,使用責任鏈模式可以很好地組織審批流程,而無需在請求發送者中硬編碼審批路徑。

代碼實現
// 抽象處理者
public abstract class ApprovalHandler {protected ApprovalHandler next;public void setNext(ApprovalHandler next) {this.next = next;}public void approve(LeaveRequest request) {if (canApprove(request)) {doApprove(request);} else if (next != null) {next.approve(request);} else {System.out.println("No approver can process the request.");}}protected abstract boolean canApprove(LeaveRequest request);protected abstract void doApprove(LeaveRequest request);
}// 具體處理者:部門經理
public class ManagerApprover extends ApprovalHandler {@Overrideprotected boolean canApprove(LeaveRequest request) {return request.getDays() <= 1;}@Overrideprotected void doApprove(LeaveRequest request) {System.out.println("Manager approved: " + request.getEmployeeName() + " for " + request.getDays() + " days.");}
}// 具體處理者:人事部
public class HRApprover extends ApprovalHandler {@Overrideprotected boolean canApprove(LeaveRequest request) {return request.getDays() > 1 && request.getDays() <= 5;}@Overrideprotected void doApprove(LeaveRequest request) {System.out.println("HR approved: " + request.getEmployeeName() + " for " + request.getDays() + " days.");}
}// 具體處理者:總經理
public class CEOApprover extends ApprovalHandler {@Overrideprotected boolean canApprove(LeaveRequest request) {return request.getDays() > 5;}@Overrideprotected void doApprove(LeaveRequest request) {System.out.println("CEO approved: " + request.getEmployeeName() + " for " + request.getDays() + " days.");}
}// 請求類
public class LeaveRequest {private String employeeName;private int days;public LeaveRequest(String employeeName, int days) {this.employeeName = employeeName;this.days = days;}public String getEmployeeName() {return employeeName;}public int getDays() {return days;}
}// 客戶端
public class LeaveApprovalSystem {public static void main(String[] args) {ApprovalHandler manager = new ManagerApprover();ApprovalHandler hr = new HRApprover();ApprovalHandler ceo = new CEOApprover();manager.setNext(hr);hr.setNext(ceo);LeaveRequest request1 = new LeaveRequest("Alice", 1);LeaveRequest request2 = new LeaveRequest("Bob", 3);LeaveRequest request3 = new LeaveRequest("Charlie", 7);manager.approve(request1); // 被部門經理處理manager.approve(request2); // 被人事部處理manager.approve(request3); // 被總經理處理}
}

在這個案例中,責任鏈模式清晰地表達了審批流程的層次結構,使系統更易于維護和擴展。例如,若以后需要增加新的審批級別,只需添加一個新的處理者并將其鏈接到鏈中即可。


與其他模式的關系

責任鏈模式常常與其他設計模式結合使用,以增強其功能或解決更復雜的問題:

模式關系說明
命令模式(Command Pattern)命令模式封裝請求為對象,責任鏈模式則處理請求鏈,二者可以結合使用,實現靈活的請求處理機制
觀察者模式(Observer Pattern)責任鏈模式關注請求的傳遞,而觀察者模式關注事件的通知,二者可以協同工作,實現事件驅動的系統
策略模式(Strategy Pattern)責任鏈模式強調處理鏈的順序,而策略模式強調算法的替換,兩者可以配合使用,實現不同的處理策略
裝飾器模式(Decorator Pattern)責任鏈模式和裝飾器模式都采用組合方式擴展對象功能,但責任鏈模式更關注請求的處理流程,而裝飾器模式更關注對象的行為增強

總結

今天我們學習了責任鏈模式的核心思想、結構、適用場景、實現方式、工作原理、優缺點分析,并通過實際項目案例進行了深入講解。責任鏈模式通過解耦請求的發送者與接收者,使得多個對象有機會處理請求,提升了系統的靈活性和可擴展性。

在Java中,責任鏈模式可以通過抽象類和鏈式引用實現,適用于審批流程、權限驗證、日志處理等多種場景。此外,責任鏈模式還可以與其他設計模式(如命令模式、觀察者模式)結合使用,進一步增強系統的功能和可維護性。

下一天我們將進入“設計模式精講”的第14天,講解命令模式(Command Pattern),敬請期待!


文章標簽

design-patterns, java, software-architecture, oop, chain-of-responsibility


文章簡述

本文詳細介紹了設計模式中的責任鏈模式(Chain of Responsibility Pattern),通過理論與實踐結合的方式,幫助Java開發工程師理解其核心思想、實現方式以及應用場景。文章提供了完整的Java代碼示例,展示了如何構建責任鏈結構,并通過企業審批系統的真實案例說明其實際價值。責任鏈模式通過解耦請求的發送者與接收者,提高了系統的靈活性和可擴展性,特別適合多級審批、權限驗證、日志處理等場景。本文不僅涵蓋了模式的基本概念,還深入分析了其與其它設計模式的關系,并提供了單元測試代碼,確保讀者能夠直接應用到實際項目中。


進一步學習資料

  1. Design Patterns: Elements of Reusable Object-Oriented Software
  2. Refactoring Guru - Chain of Responsibility
  3. Java Design Patterns - Chain of Responsibility
  4. Martin Fowler’s Patterns of Enterprise Application Architecture
  5. Head First Design Patterns

核心設計思想總結

  • 責任鏈模式通過鏈式結構傳遞請求,實現解耦與靈活處理
  • 適用于多級審批、權限驗證、日志處理等場景
  • 在Java中可通過抽象類和鏈式引用實現
  • 應避免鏈過長導致性能問題,注意邊界條件處理
  • 可與其他設計模式(如命令模式、觀察者模式)結合使用

希望本文能幫助你在實際項目中更好地理解和應用責任鏈模式,提升系統的設計質量與可維護性。

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

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

相關文章

h-ui面板 hysteria2

搭建文檔 項目地址&#xff1a;https://github.com/jonssonyan/h-ui/blob/main/README_ZH.md參考視頻&#xff1a;https://www.youtube.com/watch?vNi3iaLOsH_A一鍵部署命令 # root權限 sudo -ibash <(curl -fsSL https://raw.githubusercontent.com/jonssonyan/h-ui/mai…

自動登錄腳本神器-Mac電腦實現自動登錄堡壘機并自動輸入賬號密碼跳轉不同機器環境

先講下背景&#xff1a; 公司電腦需要先登錄堡壘機&#xff0c;然后再從堡壘機跳轉到具體生產機器&#xff0c;每次輸入堡壘機都要通過Authenticator里的2FC的碼做驗證&#xff0c;然后再跳到堡壘機還要再輸入一次賬號密碼&#xff0c;為了方便快速登錄機器&#xff0c;可以制…

【C/C++】C++26新特性前瞻:全面解析未來編程

展望未來&#xff1a;C26 新特性全面解析 隨著 C 標準每三年一次的迭代節奏&#xff0c;C26&#xff08;預計于 2026 年底正式發布&#xff09;正在逐步成型。相比 C20 的革命性更新和 C23 的“修補增強”&#xff0c;C26 繼續推進現代 C 的理念——更安全、更高效、更模塊化&…

ArXiv 2101 | Rethinking Interactive Image Segmentation Feature Space Annotation

Rethinking Interactive Image Segmentation Feature Space Annotation Author: lartpangLink: https://github.com/lartpang/blog/issues/10論文&#xff1a;https://arxiv.org/abs/2101.04378代碼&#xff1a;https://github.com/LIDS-UNICAMP/rethinking-interactive-image…

架構經驗總結

20250511-總結經驗 一、SOA 1&#xff09;過程&#xff1a;需求分析、系統設計、系統實現、構件組裝、部署運維、后開發階段。 2&#xff09;特點&#xff1a;無狀態、單一職責、明確定義接口、自包含、模塊化、粗粒度、重用性、兼容性、互操作性、松耦合、策略聲明。 3&…

debain切換 opensuse 我都安裝了什么

綠色進度條后&#xff0c;黑屏&#xff08;只有一個下劃線&#xff09;等待 使用 nomodeset 屬性解決 進入系統無法連接 wifi&#xff0c;只能使用網線連接 wifi 這個我在安裝中文字體后&#xff0c;注銷登錄&#xff0c;得到了解決&#xff0c;不確定是不是字體問題。&#x…

思科ISE/ISE-PIC安全警報:兩處高危RCE漏洞(CVSS 10.0)可致未授權獲取root權限

思科已發布更新&#xff0c;修復身份服務引擎&#xff08;Identity Services Engine&#xff0c;ISE&#xff09;及ISE被動身份連接器&#xff08;ISE-PIC&#xff09;中兩處最高危安全漏洞&#xff0c;這些漏洞可能允許未經認證的攻擊者以root用戶身份執行任意命令。 漏洞詳情…

智能助手(利用GPT搭建智能系統)

項目介紹 本項目旨在打造一個基于通義千問模型的智能助手&#xff0c;能夠理解用戶指令并自動生成可執行的 JavaScript 代碼。該代碼可直接調用預設接口&#xff0c;完成指定操作&#xff0c;并返回執行結果。通過大模型的理解與生成能力&#xff0c;實現從自然語言到接口調用…

【源碼+文檔+調試講解】基于web的運動健康小程序的設計與實現y196

摘 要 互聯網發展至今&#xff0c;無論是其理論還是技術都已經成熟&#xff0c;而且它廣泛參與在社會中的方方面面。它讓信息都可以通過網絡傳播&#xff0c;搭配信息管理工具可以很好地為人們提供服務。針對高校教師成果信息管理混亂&#xff0c;出錯率高&#xff0c;信息安全…

臨床項目計劃框架

一、項目概述 1.1 項目名稱 項目名稱:評估XX藥物在YY患者中安全性和有效性的III期隨機對照試驗 1.2 項目背景與立項依據 1.2.1 研究背景 簡述疾病負擔、當前治療現狀、未滿足的醫療需求,為項目開展提供背景支持。 1.2.2 科學依據 總結前期研究結果、理論基礎、研究假設的形…

Hoare邏輯與分離邏輯:從程序驗證到內存推理的演進

文章目錄 引言一、Hoare邏輯基礎&#xff1a;程序正確性的形式化驗證&#x1f330; 例子&#xff1a;簡單賦值語句的Hoare邏輯驗證&#x1f330; 例子&#xff1a;條件語句的Hoare邏輯驗證 二、分離邏輯&#xff1a;Hoare邏輯在內存管理中的擴展&#x1f50d; 分離邏輯的核心擴…

Tomcat Maven 插件

在 Maven 項目中&#xff0c;可以使用 Tomcat Maven 插件&#xff08;tomcat7-maven-plugin 或 tomcat-maven-plugin&#xff09;來直接部署 WAR 文件到 Tomcat 服務器&#xff0c;而無需手動復制 WAR 文件到 webapps 目錄。以下是詳細的使用方法&#xff1a; 1. 配置 Tomcat M…

【開源工具】一鍵解決使用代理后無法訪問瀏覽器網頁問題 - 基于PyQt5的智能代理開關工具開發全攻略

&#x1f310;【開源工具】一鍵解決使用代理后無法訪問瀏覽器網頁問題 - 基于PyQt5的智能代理開關工具開發全攻略 &#x1f308; 個人主頁&#xff1a;創客白澤 - CSDN博客 &#x1f525; 系列專欄&#xff1a;&#x1f40d;《Python開源項目實戰》 &#x1f4a1; 熱愛不止于代…

異步IO框架io_uring實現TCP服務器

一、io_uring介紹 io_uring是 Linux 于 2019 年加入到內核的一種新型異步 I/O 模型&#xff0c;io_uring 主要為了解決 原生AIO&#xff08;Native AIO&#xff09; 存在的一些不足之處。下面介紹一下原生 AIO 的不足之處&#xff1a; 系統調用開銷大&#xff1a;提交 I/O 操作…

【docker】docker run參數說明

功能 拉起容器。 參數 -i&#xff0c;--interactive 保持容器標準輸入放開&#xff0c;就算沒有終端也放開。 可以理解為可以向容器內輸入東西&#xff0c;比如&#xff1a; [rootlocalhost ~]# echo 111 | docker run -i yaxin:1.0 cat 111--cap-add 用于向容器添加特定的…

從0開始學習計算機視覺--Day04--損失函數

在上次學習中&#xff0c;我們知道了線性分類的函數是f(x,W),但并沒有解釋要怎么得到W權重矩陣的值&#xff0c;以及我們要怎么用訓練數據來確定它的最優權重矩陣。在之前我們知道&#xff0c;假設用了10種類別的圖片用于訓練&#xff0c;將其中一種圖片輸入模型后&#xff0c;…

【V2.0】TPS-61088升壓板-3.7V升壓到9V電源板

優化一下上一版本的升壓板&#xff1a; TPS-61088升壓板-3.7V升壓到9V電源板-CSDN博客 改動參考了官方的demo板 加了很多的電容&#xff0c;封裝很大&#xff0c;同時去掉了AGND&#xff0c;直接使用一個GND。 補償電路增加了一個47pF的電容。 EN引腳改用輸入的電壓分壓來啟…

基于DeepSeek搭建Dify智能助手國產化架構運行arm64

基于DeepSeek搭建Dify智能助手國產化架構運行arm64 基于DeepSeek搭建Dify智能助手案例介紹案例內容1 概述1.1 背景介紹1.2 適用對象1.3 案例時間1.4 案例流程1.5 資源總覽 2.啟動 Docker 容器沒有的安裝2.1沒有Docker安裝 3 云主機部署DeepSeek3.1 安裝Ollama 4.安裝Dify4.1Doc…

PyQtNode Editor 第一篇環境配置

PyQtNode Editor 以其獨特的功能和靈活的擴展性&#xff0c;吸引了眾多開發者的目光。 這篇博客作為系列開篇&#xff0c;將詳細介紹開發 PyQtNode Editor 所需的基礎環境、安裝步驟&#xff0c;同時深入解讀一段簡單的 PyQt5 代碼&#xff0c;為后續的開發工作奠定基礎。 一…

Unity 腳本自動添加頭部注釋

&#x1f4dd; Unity Script Header 注釋生成器 一個輕量、可配置的 Unity 編輯器工具&#xff0c;在創建 .cs 腳本時自動插入統一格式的注釋頭信息。 支持作者、郵箱、公司、地點、版權、描述等字段&#xff0c;所有信息都可通過 Project Settings 界面配置并動態開關。 &…