設計模式(四)——責任鏈模式

1. 責任鏈模式的定義

責任鏈模式(Chain of Responsibility,簡稱 CoR,也叫職責鏈模式)是一種行為型設計模式,允許一個請求在一系列處理器(handlers)中傳遞。每個處理器可以選擇自己處理該請求,或者將其傳遞給下一個處理器。
一個大家比較熟悉的場景是找售后客服,通常是機器人客服先出來接待,然后在你的多次要求下轉給人工客服,如果是設備維修可能還需要轉到專業人員。這個場景就很適合應用責任鏈模式。總結一下就是這個模式適用于設計靈活、解耦的請求處理流水線。
在這里插入圖片描述

2. 案例分析

2.1 需求

假設你被安排開發一個在線訂購系統。在用戶下單前,系統需要執行以下檢查:

  • 驗證用戶身份(Authenticate)
  • 若有需要,校驗管理員權限(Authorize)
  • 清理和預處理輸入數據(Sanitize)
  • 阻止重復失敗的請求(安全性)
  • 如果有緩存則直接返回緩存結果

2.2 潛在問題

如果把所有這些檢查邏輯寫在一個很長的方法里,你會發現:

  • 代碼變得冗長混亂,難維護;
  • 添加或移除檢查邏輯很麻煩;
  • 想在別處復用檢查邏輯會產生大量重復代碼。

2.3 基于責任鏈的解決方案

責任鏈模式將每個檢查邏輯封裝為獨立的處理器類(handler),在其中定義 handle() 方法來解決上述問題。
每個處理器可以自行決定:

  • 是否處理當前請求;
  • 是否將請求傳遞給下一個處理器。
    最后將這些處理器串聯起來,形成一個處理流水線(chain)
2.3.1 類定義
  • Handler(處理器接口)
  • BaseHandler(可選的抽象基類,提供鏈式調用邏輯)
  • AuthHandler(認證處理器)
  • SanitizeHandler(數據清理處理器)
  • CacheHandler(緩存處理器)
    每個處理器只需要知道下一個處理器,從而讓請求順序向下傳遞。
2.3.2 具體實現

步驟 1:定義處理器接口

interface Handler {void handle(Request request);
}

步驟 2:創建基礎處理器 BaseHandler(可選)

// BaseHandler 提供了公共邏輯,用于鏈接和轉發請求。
// 它實現了 Handler 接口。
abstract class BaseHandler implements Handler {// 保存下一個處理器的引用private Handler next;/*** 設置鏈中的下一個處理器。* 允許像這樣鏈式調用:auth.setNext(validation).setNext(logger);** @param next 下一個處理器* @return 返回傳入的處理器,用于鏈式調用*/public BaseHandler setNext(Handler next) {this.next = next;return (BaseHandler) next;}/*** 如果存在下一個處理器,則將請求轉發給它。** @param request 需要傳遞的請求對象*/protected void forward(Request request) {if (next != null) {// 委托給下一個處理器next.handle(request);  }}
}

BaseHandler 是一個抽象類,不能直接使用,而是由具體的處理器(如 AuthHandlerValidationHandler 等)繼承。
它封裝了職責鏈的核心邏輯:

  • setNext() 設置下一個處理器并返回它,以便鏈式調用;
  • forward() 將請求傳遞給下一個處理器。

具體處理器類只需要關注自身的 handle() 邏輯,執行完后調用 forward(request) 即可。

步驟 3:定義請求對象

class Request {public String user;public boolean isAdmin;public boolean isValid = true;public boolean isCached;// ... 字段可以根據需要擴展
}

步驟 4:創建具體的處理器

// Handler 1: 檢查用戶是否已登錄
class AuthHandler extends BaseHandler {@Overridepublic void handle(Request request) {if (request.user == null) {System.out.println("[Auth] 用戶未認證,請求終止。");// 不再向下傳遞return; }System.out.println("[Auth] 用戶已認證。");// 交給下一個處理器forward(request); }
}// Handler 2: 管理員權限校驗
class AdminHandler extends BaseHandler {@Overridepublic void handle(Request request) {if (!request.isAdmin) {System.out.println("[Admin] 普通用戶,跳過管理員校驗。");} else {System.out.println("[Admin] 管理員驗證通過。");// 可執行管理員相關邏輯}forward(request);}
}// Handler 3: 數據清理
class SanitizeHandler extends BaseHandler {@Overridepublic void handle(Request request) {System.out.println("[Sanitize] 正在清理數據...");forward(request);}
}

步驟 5:組裝責任鏈

public class ChainApp {public static void main(String[] args) {Request request = new Request();request.user = "哈基米";request.isAdmin = true;Handler chain = new AuthHandler();chain.setNext(new AdminHandler()).setNext(new SanitizeHandler());chain.handle(request);}
}
2.3.3 執行流程
  1. AuthHandler 驗證用戶;
  2. 驗證通過后,將請求傳遞給 AdminHandler
  3. 再傳遞到 SanitizeHandler
  4. 如果某個處理器中斷了鏈條,后續處理器將不會執行。

3. 優缺點分析

3.1 優勢

  • 處理器可復用,且易于單元測試;
  • 可以在運行時動態配置責任鏈;
  • 邏輯清晰,符合 單一職責原則(SRP)
  • 處理順序不在處理器內部硬編碼,而是通過鏈式結構靈活定義。

3.2 缺點

  • 如果鏈條覆蓋不全,可能存在請求未被處理的情況;
  • 請求在長鏈路中傳遞時,跟蹤路徑可能較困難;
  • 動態鏈條的調試可能比較復雜,需要設計合適的日志記錄方式。

4. 使用

4.1 常見應用場景

  • 中間件管道(認證、校驗、日志記錄)
  • GUI 事件處理(鼠標/鍵盤事件)
  • 垃圾郵件過濾
  • 文件格式識別

4.2 適用場景

當滿足以下條件時,可以考慮使用職責鏈模式:

  • 有多個對象可以處理同一個請求;
  • 需要解耦請求發送方和接收方;
  • 需要復用或動態調整處理邏輯順序;
  • 需要在某些條件下提前終止處理流程。

總結

**職責鏈模式的核心在于靈活性。**使得邏輯可以像流水線一樣串聯起來,每個處理器專注于一個小任務。合理的使用這種模式可以讓代碼邏輯更加清晰、便于測試和擴展,還能避免冗長的條件分支。

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

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

相關文章

MyBatis-Plus基礎篇詳解

文章目錄前言一、簡單介紹MyBatis-Plus1.1 特性1.2 架構二、SpringBoot集成MyBatis-Plus2.1 項目搭建2.2 導入所需依賴2.3 配置application.yml2.4 創建實體類2.5 創建Mapper接口2.6 啟動類配置三、DQL操作3.1 基礎查詢3.2 QueryWrapper查詢3.3 LambdaQueryWrapper查詢3.4 分頁…

基于W55MH32Q-EVB 實現 HTTP 服務器配置 OLED 滾動顯示信息

目錄 1 前言 2 項目環境 2.1 硬件準備 2.2 軟件環境 3.硬件連接和方案 3.1 硬件連接 3.2 方案圖示 4.例程修改 1 前言 HTTP(超文本傳輸協議,HyperText Transfer Protocol)是一種用于分布式、協作式、超媒體信息系統的應用層協議, …

YggJS RLogin暗黑霓虹主題登錄注冊頁面 版本:v0.1.1

項目介紹 yggjs_rlogin 是一個專注于 React 登錄/注冊頁面的組件庫。本文檔介紹“暗黑霓虹”主題:#111 暗色背景 青藍霓虹描邊輸入框 賽博朋克光效按鈕。 安裝說明 安裝:pnpm add yggjs_rlogin react react-dom使用:從 yggjs_rlogin 引入組…

大數據畢業設計選題推薦:護膚品店鋪運營數據可視化分析系統詳解

🍊作者:計算機畢設匠心工作室 🍊簡介:畢業后就一直專業從事計算機軟件程序開發,至今也有8年工作經驗。擅長Java、Python、微信小程序、安卓、大數據、PHP、.NET|C#、Golang等。 擅長:按照需求定制化開發項目…

【github-action 如何為github action設置secrets/environment】

Using secrets in GitHub Actions 在 GitHub Actions 中使用密鑰 Learn how to create secrets at the repository, environment, and organization levels for GitHub Actions workflows. 學習如何在倉庫、環境和組織級別為 GitHub Actions 工作流創建密鑰。 Creating secre…

寶塔面板Docker安裝n8n漢化中文

一、Docker安裝N8N 安裝配置默認即可,如果端口已被使用,可以自行更改 當狀態為運行中時,就可以點擊端口:訪問N8N 填寫完信息后,點擊下一步(郵箱要能接收郵件:接收密鑰) 點開始 點擊發…

F003疫情傳染病數據可視化vue+flask+mysql

編號:F003 文章結尾有CSDN官方提供的學長的聯系方式!! 歡迎關注B站 ? vue flask 前后端分離架構 ? 實現中國地圖、柱狀圖、折線圖、水地圖、環圖等多種圖形的echarts可視化分析 視頻 vueflask爬蟲 新冠疫情大屏實現 python 可視化分析項目源碼1 系統…

plantsimulation知識點25.8.19 工件不在RGV中心怎么辦?

如果出現這種情況,工件不在RGV的中心該怎么處理。首先說一下出現這種情況的原因。因為模擬的是兩臺RGV共同托舉一個工件移動,實際上RGV控制的代碼還是寫在一條軌道的傳感器控制代碼中。另一臺RGV只是從動的,工件也是在其中任意一臺RGV上&…

redis-sentinel基礎概念及部署

一. 引言:Redis Sentinel 是 redis 官方提供的高可用解決方案,主要用于監控 Redis 主從集群,在主節點故障時自動完成故障轉移,確保服務持續可用。二. 核心功能1. 監控(monitoring):持續檢查主節…

LangChain RAG 簡述

在 LangChain 中實現 RAG(檢索增強生成,Retrieval-Augmented Generation)的核心思路是:讓大模型在生成回答前,先從外部知識庫(如文檔、數據庫等)中檢索相關信息,再基于檢索到的內容生…

GEO 優化專家孟慶濤:技術破壁者重構 AI 時代搜索邏輯

在生成式 AI 重塑全球搜索生態的浪潮中,中國 GEO(生成式引擎優化)領域的開拓者孟慶濤以 "智能決策革命" 的技術框架,顛覆了傳統 "發發文章" 的簡單認知。作為遼寧粵穗網絡科技有限公司總經理兼 GEO 實驗室主任…

用relation-graph構建關系圖譜 vue版

用relation-graph構建關系圖譜 vue版vue文件和Json數據vue文件和Json數據 <template><div><div style"margin-top:0px;width: calc(100% - 10px);height:calc(100vh);"><RelationGraph ref"graphRef" :options"graphOptions&qu…

Python基礎-控制結構

控制結構是編程語言中用來控制程序執行流程的語句。Python提供了條件語句、循環語句等控制結構&#xff0c;讓程序能夠根據不同條件執行不同的代碼塊。 程序執行流程圖&#xff1a; ┌───────────────────────────────────────────…

Java算法之排序

下面我們將講述七大基于比較的排序算法的基本原理及實現。并從穩定性、時間復雜度、空間復雜度3種性能對每種排序進行分析。 重點&#xff1a;快速排序和堆排序&#xff1b;難點&#xff1a;快速排序和歸并排序 目錄 一、排序概念 二、常見排序算法的實現 2.1 插入排序 2.…

RabbitMQ:SpringAMQP 多消費者綁定同一隊列

目錄一、案例需求二、代碼實現三、總結生產者源碼 消費者源碼 一、案例需求 模擬WorkQueue&#xff0c;實現一個隊列綁定多個消費者。 在RabbitMQ的控制臺創建一個隊列&#xff0c;命名為work.queue。在生產者服務中定義測試方法&#xff0c;在1s內產生50條消息&#xff0c;…

Java技術總監的成長之路(技術干貨分享)

以下是針對 ?Java技術總監? 在 Linux 環境下搭建企業級開發環境的完整指南&#xff0c;涵蓋 JDK 配置、工程工具鏈、協作平臺及性能優化方案&#xff1a; 本文章僅提供學習&#xff0c;切勿將其用于不法手段&#xff01; 一、核心環境搭建 1. ?JDK 安裝與調優? ?版本選擇…

C++代碼解釋:實現一個 mystring 類,用于表示字符串,實現構造函數,默認構造長度為 10 的空間,提供打印字符串,獲取空間大小,修改內容的成員函數

題目代碼#include <cstring> // 包含字符串處理函數庫&#xff0c;如strlen、strncpy等 #include <iostream> // 包含輸入輸出流庫&#xff0c;用于cout等操作 using namespace std; // 使用標準命名空間&#xff0c;避免重復書寫std::class mystring { // 定…

如何解決IDEA/Datagrip無法連接數據庫的問題:解決方法為添加參數-Djava.net.preferIPv4Stack=true

如何解決IDEA/Datagrip無法連接數據庫的問題&#xff1a;解決方法為添加參數-Djava.net.preferIPv4Stacktrue 引言 在開發過程中&#xff0c;我們常常使用集成開發環境&#xff08;IDE&#xff09;如 IntelliJ IDEA 或 JetBrains DataGrip 來與數據庫進行交互。然而&#xff…

走進數字時代,融入數字生活,構建數字生態

一、準備在IT行業深耕十七年&#xff0c;始終專注于企業生產經營中的實際應用問題&#xff0c;歷經開發、測試、運維、實施、架構設計等多個技術崗位&#xff0c;并參與肉制品的生產與銷售業務&#xff0c;推進了企業主業的市場管理落地&#xff0c;積累了業務與信息技術融合的…

【Vue開發】在Vite+Vue3項目中實現離線Iconify圖標方案

在ViteVue3項目中實現離線Iconify圖標方案 項目背景 當前項目需要部署到無網絡連接的離線環境&#xff0c;因此需要將Iconify圖標集打包到項目構建結果中&#xff0c;實現完全離線使用。 技術環境 框架: Vue 3構建工具: Vite核心依賴:"iconify/json": "^2.2…