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

責任鏈模式在 Java 中的實戰應用:從純粹到實用的演進

     編輯:Java 相關知識

模式緣起與核心定義

責任鏈模式 旨在 解耦請求發送者與接收者。多個處理者組成鏈條,請求沿鏈傳遞,直到某處理者處理為止。

GoF 定義:使多個對象都有機會處理請求,從而避免發送者和接收者耦合。將對象連成鏈,沿鏈傳遞請求,直到有對象處理它。

適用場景

  1. 多個對象可處理同一請求,具體處理者運行時確定
  2. 不明確指定接收者,向多對象之一提交請求
  3. 可處理請求的對象集合動態指定

兩大角色

角色職責
抽象處理者 定義處理請求介面;可選:定義後繼者引用與鏈接邏輯
具體處理者 實現處理邏輯;若無法處理則委派給後繼者

純粹 vs 不純粹責任鏈

維度純粹模式不純粹模式
處理者行為二選一:完全處理 或 轉發下家可部分處理後轉發;可全部嘗試處理
請求必被處理是否 (可無果而終)
典型場景嚴格分級審批、過濾器鏈日誌記錄、多策略嘗試、事件廣播

實務建議:不要為符合教科書定義而強行純粹。降低耦合、提高復用、適應變化 才是衡量標準。「管它黑貓白貓,抓住老鼠就是好貓。」

實戰案例:代號自動生成器重構

業務背景

系統需生成員工工號、檔案代號等,規則包含變動元素:年份、月份、日期、流水號。初期硬編碼,後期需擴展新元素。

重構前 (硬編碼)

public String generateCode(String rule) {
    String result = rule;
    result = result.replace("{YYYY}", currentYear());
    result = result.replace("{MM}", currentMonth());
    result = result.replace("{DD}", currentDay());
    result = result.replace("{SEQ}", nextSequence());
    return result;
}

問題:違反開閉原則,新增元素需修改核心邏輯。

重構後:責任鏈實現

1. 統一介面

public interface CodeAutoParse {
    String[] generateCode(String moduleCode, int number, String rule, String[] target) throws BaseException;
}

2. 具體處理者:日期解析器

public class DateAutoParse implements CodeAutoParse {
    private final Calendar currentDate = Calendar.getInstance();
    private CodeAutoParse nextParser; // Spring 注入

    public void setNextParser(CodeAutoParse nextParser) {
        this.nextParser = nextParser;
    }

    @Override
    public String[] generateCode(String moduleCode, int number, String rule, String[] target) throws BaseException {
        // 1. 解析規則中的日期佔位符
        // 2. 更新 target 陣列
        // ...
        
        // 3. 委派下一個處理者 (不純粹模式:無論是否處理都傳遞)
        if (nextParser != null) {
            return nextParser.generateCode(moduleCode, number, rule, target);
        }
        return target;
    }
}

3. 其他處理者:SequenceAutoParse、CustomFieldAutoParse 等,結構相同

4. Spring 配置鏈路 (關鍵:外部化鏈路組裝)

<bean id="dateParser" class="com.example.DateAutoParse">
    <property name="nextParser" ref="sequenceParser"/>
</bean>

<bean id="sequenceParser" class="com.example.SequenceAutoParse">
    <property name="nextParser" ref="customFieldParser"/>
</bean>

<bean id="customFieldParser" class="com.example.CustomFieldAutoParse">
    <property name="nextParser" ref="null"/> <!-- 鏈尾 -->
</bean>

新增處理者只需:實現介面 + 修改 Spring 配置,零修改現有代碼。

5. 客戶端調用

@Autowired
private CodeAutoParse firstParser; // 注入鏈頭

public String[] generate(String moduleCode, int number, String rule) {
    return firstParser.generateCode(moduleCode, number, rule, new String[number]);
}

進階優化與變體

1. 處理者優先級動態排序

@Component
public class PriorityChainBuilder implements InitializingBean {
    @Autowired
    private List parsers; // 所有處理者
    
    private CodeAutoParse head;
    
    @Override
    public void afterPropertiesSet() {
        parsers.sort(Comparator.comparingInt(CodeAutoParse::getPriority));
        for (int i = 0; i < parsers.size() - 1; i++) {
            parsers.get(i).setNextParser(parsers.get(i + 1));
        }
        head = parsers.get(0);
    }
    
    public CodeAutoParse getHead() { return head; }
}

2. 條件式處理者 (針對特定模組/規則類型)

public class ConditionalParser implements CodeAutoParse {
    private final Predicate condition;
    private final CodeAutoParse delegate;
    
    @Override
    public String[] generateCode(...) {
        if (condition.test(rule)) {
            return delegate.generateCode(...);
        }
        return nextParser != null ? nextParser.generateCode(...) : target;
    }
}

3. 異常處理與熔斷

  • 處理者拋出異常 → 記錄日誌、決定是否中斷鏈路或繼續傳遞
  • 引入 CircuitBreaker 防止級聯失效

效能考量與避坑指南

風險對策
鏈路過長導致延遲控制處理者數量;關鍵路徑避免深層鏈路
循環引用 (A→B→A)啟動時檢測;Spring 循環依賴檢查
執行緒安全 (共享狀態)處理者設計為無狀態;必要時 ThreadLocal
除錯困難鏈路執行日誌記錄處理者進入/退出/耗時

總結

責任鏈模式通過 介面統一 + 鏈路外部化配置,實現了處理邏輯的模組化、動態組合與零侵入擴展。核心價值在於 「誰處理、按什麼順序、能否動態調整」 這三個決策從業務代碼中剝離。實務中採用不純粹模式、Spring 組裝鏈路、引入優先級/條件/熔斷機制,是企業級應用的成熟做法。

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