首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 設計模式精講:責任鏈模式原理、UML、實戰代碼與優缺點全分析

     編輯:Java 相關知識

責任鏈模式是行為型設計模式的經典代表,通過將請求處理者串聯成鏈,實現請求發送者與接收者的解耦。本文系統講解其核心角色、UML 結構、Java 完整實現、Web 過濾器/攔截器中的實戰應用、優缺點權衡及擴展變體。

一、 模式動機與適用場景

核心思想:將請求處理細節(由誰處理、怎麼處理、按什麼順序)從客戶端代碼中剝離,封裝在鏈式結構中。客戶端只需將請求發送給鏈頭,無需關心後續流轉邏輯。

典型應用場景

  1. 多級審批/處理流程:請假審批(組長→經理→總監→VP)、訂單風控(規則引擎→人工覆核→自動通過)。
  2. Web 中間件管道:Servlet Filter 鏈、Spring MVC HandlerInterceptor 鏈、Netty ChannelPipeline、Dubbo Filter 鏈。
  3. 日誌/異常處理鏈:Log4j2 Logger 繼承鏈、Spring HandlerExceptionResolver 鏈。
  4. 事件總線/命令總線:命令依次經過驗證、權限、緩存、持久化、發布等處理器。

二、 UML 類圖與核心角色

責任鏈模式 UML 類圖

角色職責關鍵方法
Handler (抽象處理者) 定義處理請求的接口,可選持有後繼者引用 handleRequest(Request), setNext(Handler)
ConcreteHandler (具體處理者) 處理自己能處理的請求,否則傳遞給後繼者 重寫 handleRequest
Client (客戶端) 組裝鏈結構,發起請求 調用 headHandler.handleRequest(req)

三、 Java 經典實現

1. 抽象處理者基類

public abstract class Handler {
    protected Handler successor;
    
    public abstract void handleRequest(String condition);
    
    public Handler getSuccessor() { return successor; }
    public void setSuccessor(Handler successor) { this.successor = successor; }
    
    // 模板方法:處理完畢自動傳遞
    protected void passToNext(String condition) {
        if (successor != null) {
            successor.handleRequest(condition);
        }
    }
}

2. 具體處理者

public class ConcreteHandler1 extends Handler {
    @Override
    public void handleRequest(String condition) {
        System.out.println("ConcreteHandler1 處理請求: " + condition);
        // 業務邏輯...
        passToNext(condition); // 傳遞給下一個
    }
}

public class ConcreteHandler2 extends Handler {
    @Override
    public void handleRequest(String condition) {
        System.out.println("ConcreteHandler2 處理請求: " + condition);
        passToNext(condition);
    }
}

public class ConcreteHandler3 extends Handler {
    @Override
    public void handleRequest(String condition) {
        System.out.println("ConcreteHandler3 處理請求: " + condition);
        // 最後一個可選擇不傳遞,或傳遞給終結節點
        passToNext(condition);
    }
}

3. 客戶端組裝與調用

public class Client {
    public static void main(String[] args) {
        Handler h1 = new ConcreteHandler1();
        Handler h2 = new ConcreteHandler2();
        Handler h3 = new ConcreteHandler3();
        
        // 建立鏈:h1 → h2 → h3
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);
        
        // 發起請求
        h1.handleRequest("訂單創建請求");
    }
}

四、 進階變體:純鏈 vs 處理後終止

  • 簡單審批流
  • 日誌級別過濾
  • Web 過濾器管道
  • AOP 攔截器鏈
  • Netty ChannelPipeline
  • 插件化架構
  • 中間件自動裝配
  • 變體特點適用場景
    純責任鏈 每個處理者要么全權處理,要么完全傳遞,不允許部分處理後傳遞
    不純責任鏈 處理者可部分處理後傳遞,或處理完仍傳遞(如 Servlet Filter chain.doFilter() 前後邏輯)
    動態鏈構建 運行時根據配置/註解動態組裝順序(Spring @Order、Dubbo @Activate)

    五、 實戰:Servlet Filter 鏈源碼剖析

    // ApplicationFilterChain 核心邏輯 (Tomcat 簡化版)
    public final class ApplicationFilterChain implements FilterChain {
        private final List filters = new ArrayList<>();
        private int position = 0;
        
        @Override
        public void doFilter(ServletRequest request, ServletResponse response) {
            if (position < filters.size()) {
                Filter filter = filters.get(position++);
                filter.doFilter(request, response, this); // 關鍵:傳遞 this (鏈對象)
            } else {
                // 終點:調用 Servlet.service()
                servlet.service(request, response);
            }
        }
        
        public void addFilter(Filter filter) { filters.add(filter); }
    }
    

    關鍵設計:FilterChain 作為鏈對象傳遞,filter.doFilter(req, res, chain) 由開發者決定是否調用 chain.doFilter() 及調用前後邏輯,極其靈活。

    六、 優缺點深度權衡

    優點

    1. 降低耦合度:發送者無需知道接收者具體類、處理順序、處理邏輯。
    2. 靈活組合:運行時動態增減/調序處理者,無需修改客戶端代碼(開閉原則)。
    3. 單一職責:每個處理者專注單一業務邏輯,易測試、易維護。
    4. 避免巨大條件判斷:替代冗長的 if-else if-else 鏈。

    缺點

    1. 請求可能未被處理:鏈尾無處理者、配置錯誤導致請求「石沉大海」,難以發現。
    2. 調試困難:運行時鏈結構動態、請求流轉路徑不直觀,需靈活的日誌/追蹤機制。
    3. 性能開銷:鏈過長、對象創建頻繁、方法調用棧深,高頻熱點路徑需關注。
    4. 循環引用風險:誤配置導致環狀鏈,造成棧溢出。

    七、 最佳實踐建議

    1. 明確終結條件:提供默認終結處理者(記錄未處理請求、拋出異常、返回默認響應)。
    2. 引入順序控制:@Order、優先級字段、拓撲排序,保證鏈順序確定性。
    3. 統一日誌埋點:每個處理者入口/出口打印 Trace ID、處理者名、耗時,構建可觀測鏈路。
    4. 限制鏈長度:核心業務鏈建議 < 10 節點,過長拆分為多級管道。
    5. 考慮異步/響應式擴展:Reactor Mono/Flux 鏈、CompletableFuture 鏈,避免阻塞線程。

    八、 總結

    責任鏈模式以「鏈式委託」替代「集中控制」,是構建可擴展、低耦合處理管道的利器。從 Servlet Filter 到 Spring Interceptor,從 Netty Pipeline 到 Dubbo Filter,它是 Java 生態中中間件、框架、業務流程引擎的基石架構。掌握其純/不純變體、動態組裝、調試觀測、性能調優,是高級 Java 開發者的必備架構能力。

    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved