摘要
責任鏈設計模式是一種行為型設計模式,旨在將請求的發送者與接收者解耦,通過多個處理器對象按鏈式結構依次處理請求,直到某個處理器處理為止。它包含抽象處理者、具體處理者和客戶端等核心角色。該模式適用于多個對象可能處理請求的場景,如風控系統中的貸款申請流程,通過鏈式組合處理整個流程。實現方式包括鏈式引用和集合遍歷等,適用于信貸申請風控校驗等實際應用。
1. 責任鏈設計模式定義
責任鏈設計模式(Chain of Responsibility Pattern)是一種行為型設計模式,允許多個處理器對象都有機會處理請求,避免請求的發送者與接收者之間的耦合關系。這些處理器按照鏈式結構連接,每個處理器決定是否處理請求,或將其傳遞給鏈上的下一個處理器。
1.1.1. ? 責任鏈設計模式定義要點:
項目 | 內容 |
目的 | 將請求的發送者與接收者解耦,讓多個對象有機會處理請求。 |
結構 | 每個處理者持有對下一個處理者的引用,形成鏈式結構。 |
核心機制 | 請求沿鏈傳遞,直到被某個處理者處理為止。 |
關鍵點 | 不關心請求由誰處理,處理器職責明確,鏈條可靈活組合。 |
1.1.2. ? UML 類圖核心角色:
- Handler(抽象處理者):定義處理請求的接口,維護下一個處理者引用。
- ConcreteHandler(具體處理者):實現處理邏輯,判斷是否處理請求,否則傳遞。
- Client(客戶端):構建責任鏈并發起請求。
1.1.3. ? 示例場景說明(以風控為例):
風控系統中,一條貸款申請請求需要依次經過:
黑名單檢查 → 信用評分檢查 → 欺詐風險檢查 → 額度判斷
每個檢查環節都是一個責任節點,最終鏈式組合處理整個申請流程。
2. 責任鏈設計模式結構
2.1. 責任鏈設計模式類圖
- 處理者 (Handler) 聲明了所有具體處理者的通用接口。
- 基礎處理者 (Base Handler) 是一個可選的類, 你可以將所有處理者共用的樣本代碼放置在其中。
- 具體處理者 (Concrete Handlers) 包含處理請求的實際代碼。 每個處理者接收到請求后, 都必須決定是否進行處理, 以及是否沿著鏈傳遞請求。
- 客戶端 (Client) 可根據程序邏輯一次性或者動態地生成鏈。 值得注意的是, 請求可發送給鏈上的任意一個處理者, 而非必須是第一個處理者。
3. 責任鏈設計模式實現方式
責任鏈設計模式的實現方式有兩種主要形式:鏈式引用方式 和 集合遍歷方式。在 Java 和 Spring 項目中,兩種方式都可以靈活使用,以下是詳細實現說明:
3.1. ? 鏈式引用方式(經典責任鏈)
3.1.1. 定義抽象處理器
public abstract class RiskHandler {protected RiskHandler next;public void setNext(RiskHandler next) {this.next = next;}public void handle(Request request) {if (doHandle(request) && next != null) {next.handle(request);}}protected abstract boolean doHandle(Request request);
}
3.1.2. 實現具體處理器
@Component
public class BlacklistHandler extends RiskHandler {@Overrideprotected boolean doHandle(Request request) {System.out.println("黑名單校驗");// 模擬通過return true;}
}@Component
public class CreditScoreHandler extends RiskHandler {@Overrideprotected boolean doHandle(Request request) {System.out.println("信用評分校驗");return true;}
}
3.1.3. 構造責任鏈(可由 Spring 初始化)
@Component
public class RiskChainBuilder {@Autowiredprivate BlacklistHandler blacklistHandler;@Autowiredprivate CreditScoreHandler creditScoreHandler;@PostConstructpublic void init() {blacklistHandler.setNext(creditScoreHandler);// 可繼續設置下一個}public RiskHandler getChain() {return blacklistHandler;}
}
3.2. ? 集合遍歷方式(策略+責任鏈)
這種方式更適合使用 Spring 管理 Bean。
3.2.1. 定義統一接口
public interface RiskHandler {boolean handle(Request request);
}
3.2.2. 實現多個處理器(用注解自動注入)
@Component
public class BlacklistHandler implements RiskHandler {public boolean handle(Request request) {System.out.println("黑名單處理");return true;}
}@Component
public class CreditHandler implements RiskHandler {public boolean handle(Request request) {System.out.println("信用處理");return true;}
}
3.2.3. 責任鏈執行器
@Component
public class RiskChainExecutor {@Autowiredprivate List<RiskHandler> handlers;public void process(Request request) {for (RiskHandler handler : handlers) {if (!handler.handle(request)) {break; // 攔截處理}}}
}
3.3. ? 責任鏈實現方式總結
項目 | 鏈式引用方式 | 集合遍歷方式 |
Spring友好 | 較差,需要手動串聯 | 非常友好,自動注入 List |
動態配置順序 | 不方便(寫死在代碼) | 可通過 |
靈活性 | 靈活,可動態組合鏈 | 更適合順序一致、處理流程清晰 |
推薦程度 | 簡單鏈條推薦使用 | 企業級風控強烈推薦 |
4. 責任鏈設計模式適合場景
4.1. ? 適合使用責任鏈設計模式的場景
場景 | 說明 |
多個對象可以處理同一請求 | 請求的處理者不唯一,多個處理器具備處理能力。 |
處理邏輯具有先后順序且可拆分 | 如風控流程、審批流程、日志處理、事件流轉等。 |
希望動態添加或修改處理邏輯鏈 | 支持運行時動態組合處理器鏈條,提高靈活性。 |
解耦請求與處理器之間的關系 | 請求發送者無需知道誰會處理,只需交給鏈處理。 |
處理節點對請求是否繼續傳遞有決策權 | 允許部分處理節點終止請求,如認證失敗即停止。 |
4.2. ? 不適合使用責任鏈設計模式的場景
場景 | 原因 |
處理流程固定,結構簡單 | 使用責任鏈會增加結構復雜度,得不償失。 |
必須同時執行所有處理邏輯,不允許中斷 | 責任鏈是短路模型(遇到失敗可中斷),不適合要求“全部執行”的場景。 |
處理者之間高度耦合或依賴上下文共享 | 處理節點應獨立,依賴過多會降低可維護性。 |
對性能要求極高、鏈條很長 | 每次請求都需遍歷鏈條,可能帶來額外性能損耗。 |
請求必須同時由多個處理器并行處理 | 責任鏈是串行模式,不適合并行處理場景。 |
4.3. 📌 實際應用建議
使用責任鏈的條件 | 建議 |
節點解耦 + 處理器獨立 + 順序可變 | ? 可考慮使用 |
所有處理器必須全執行,順序固定 | ? 不推薦,改用責任集(全執行)或責任調度中心 |
所有邏輯都寫死在 if-else 中 | ? 可用責任鏈重構,提高擴展性和可維護性 |
5. 責任鏈設計模式實戰示例
5.1. ? 應用場景:信貸申請風控校驗
系統在用戶提交借款申請時,需要依次執行以下校驗邏輯(處理鏈):
- 黑名單校驗
- 實名認證校驗
- 信用評分校驗
5.2. 🧩 請求對象
public class LoanRequest {private String userId;private String name;private int age;// 其他信息// getter/setter省略
}
5.3. 🧩 風控處理器接口
public interface RiskHandler {/*** 返回 true 表示通過校驗,繼續執行后續處理器;false 表示終止處理。*/boolean handle(LoanRequest request);
}
5.4. 🧩 風控處理器實現(舉例4個)
5.4.1. 🔹 黑名單校驗器
@Component
@Order(1)
public class BlacklistHandler implements RiskHandler {@Overridepublic boolean handle(LoanRequest request) {System.out.println("黑名單校驗: " + request.getUserId());// 假設用戶不在黑名單中return true;}
}
5.4.2. 🔹 實名認證校驗器
@Component
@Order(2)
public class RealNameHandler implements RiskHandler {@Overridepublic boolean handle(LoanRequest request) {System.out.println("實名認證校驗: " + request.getName());return true;}
}
5.4.3. 🔹 信用評分校驗器
@Component
@Order(3)
public class CreditScoreHandler implements RiskHandler {@Overridepublic boolean handle(LoanRequest request) {System.out.println("信用評分校驗: " + request.getUserId());return true;}
}
5.4.4. 🔹 反欺詐規則校驗器
@Component
@Order(4)
public class AntiFraudHandler implements RiskHandler {@Overridepublic boolean handle(LoanRequest request) {System.out.println("反欺詐校驗: " + request.getUserId());return true;}
}
5.5. 🧩 風控責任鏈執行器(接口變實現遍歷)
@Component
public class RiskCheckExecutor {@Autowiredprivate List<RiskHandler> handlers;public boolean execute(LoanRequest request) {for (RiskHandler handler : handlers) {if (!handler.handle(request)) {System.out.println("風控攔截,終止流程");return false;}}System.out.println("所有風控校驗通過");return true;}
}
@Order
確保處理器執行順序一致。
5.6. 🧩 測試調用示例(如用于 Controller)
@RestController
@RequestMapping("/loan")
public class LoanController {@Autowiredprivate RiskCheckExecutor executor;@PostMapping("/apply")public ResponseEntity<String> apply(@RequestBody LoanRequest request) {boolean pass = executor.execute(request);if (pass) {return ResponseEntity.ok("風控通過,進入審批");} else {return ResponseEntity.status(HttpStatus.FORBIDDEN).body("風控未通過");}}
}
5.7. ? 項目示例總結
特性 | 說明 |
注解注入 | 使用 |
避免構造函數 | 所有注入均為字段注入,無需構造器方式 |
解耦結構 | 每個處理器職責單一,互不干擾 |
可擴展性 | 增加校驗邏輯僅需新增實現類并加上 |
6. 責任鏈設計模式思考
博文參考
- https://github.com/guanguans/design-patterns-for-humans-cn