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

Java 責任鏈模式實戰:請假審批流程引擎,動態組裝處理節點

     編輯:Java 相關知識

責任鏈模式將請求發送者與多個接收者解耦,請求沿鏈路傳遞直到被處理。本文以「多級請假審批」為例,展示如何將組長/部門主管/總經理封裝為獨立處理節點,動態組裝審批鏈,新增角色零修改核心代碼。

核心角色

  • Handler(抽象處理者):定義處理方法、持有 nextHandler 引用
  • ConcreteHandler(具體處理者):實現具體審批邏輯,決定處理或轉發
  • Request(請求對象):攜帶業務數據(申請人、天數、事由)

完整代碼實現

// 請求對象
class LeaveRequest {
    private String applicant;
    private int days;
    private String reason;
    // 構造器、getter/setter 省略
}

// 抽象處理者
abstract class Approver {
    protected String name;
    protected Approver nextApprover;
    public Approver(String name) { this.name = name; }
    public void setNext(Approver next) { this.nextApprover = next; }
    public abstract void handle(LeaveRequest request);
}

// 具體處理者:組長(<3天)
class GroupLeader extends Approver {
    public GroupLeader(String name) { super(name); }
    public void handle(LeaveRequest req) {
        if (req.getDays() < 3) {
            printApproved(req, "組長");
        } else {
            System.out.println(name + "(組長)權限不足,轉交上級");
            if (nextApprover != null) nextApprover.handle(req);
        }
    }
}

// 具體處理者:部門主管(<10天)
class DeptManager extends Approver {
    public DeptManager(String name) { super(name); }
    public void handle(LeaveRequest req) {
        if (req.getDays() < 10) {
            printApproved(req, "部門主管");
        } else {
            System.out.println(name + "(主管)權限不足,轉交上級");
            if (nextApprover != null) nextApprover.handle(req);
        }
    }
}

// 具體處理者:總經理(<30天)
class GeneralManager extends Approver {
    public GeneralManager(String name) { super(name); }
    public void handle(LeaveRequest req) {
        if (req.getDays() < 30) {
            printApproved(req, "總經理");
        } else {
            printRejected(req, "總經理");
        }
    }
}

// 通用打印方法
void printApproved(LeaveRequest req, String role) {
    System.out.println("===== 審批通過 =====");
    System.out.println("申請人:" + req.getApplicant() + " | 天數:" + req.getDays() + " | 事由:" + req.getReason());
    System.out.println("審批人:" + role + "(通過)");
}
void printRejected(LeaveRequest req, String role) {
    System.out.println("===== 審批駁回 =====");
    System.out.println("申請人:" + req.getApplicant() + " | 天數:" + req.getDays() + " | 事由:" + req.getReason());
    System.out.println("審批人:" + role + "(駁回:超過權限上限)");
}

// 客戶端:動態組裝鏈路
public class Demo {
    public static void main(String[] args) {
        Approver leader = new GroupLeader("張三");
        Approver manager = new DeptManager("李四");
        Approver gm = new GeneralManager("王五");
        
        // 組裝鏈路:組長 → 主管 → 總經理
        leader.setNext(manager);
        manager.setNext(gm);
        
        // 測試不同天數
        leader.handle(new LeaveRequest("小王", 2, "感冒"));    // 組長通過
        leader.handle(new LeaveRequest("小李", 5, "結婚"));    // 主管通過
        leader.handle(new LeaveRequest("小張", 15, "產假"));   // 總經理通過
        leader.handle(new LeaveRequest("小趙", 35, "環遊世界")); // 總經理駁回
    }
}

優勢分析

傳統 if-else責任鏈模式
審批邏輯集中在一個巨大方法中每個角色邏輯獨立封裝在單獨類中
新增角色需修改核心方法(違反開閉原則)新增角色只需新建類並接入鏈路
順序調整需修改代碼邏輯僅調整 setNext 組裝順序
難以單元測試單個角色邏輯每個處理者可獨立測試
職責邊界模糊單一職責原則,邊界清晰

企業級應用場景

  • Servlet Filter 鏈:FilterChain.doFilter 標準責任鏈
  • Spring Interceptor:HandlerInterceptor 鏈式調用
  • Struts2 Interceptor Stack:攔截器棧
  • 權限校驗鏈:認證 → 授權 → 限流 → 日誌
  • 異常處理鏈:業務異常 → 系統異常 → 降級 → 錯誤頁

進階:配置化組裝

生產環境建議將鏈路組裝外部化配置:

# application.yml
approval-chain:
  - com.approval.GroupLeader
  - com.approval.DeptManager
  - com.approval.GeneralManager

// Spring 啟動時按順序自動注入構建鏈路
@Component
public class ApprovalChainBuilder {
    @Autowired List<Approver> approvers;
    public Approver build() {
        for (int i = 0; i < approvers.size() - 1; i++) {
            approvers.get(i).setNext(approvers.get(i + 1));
        }
        return approvers.get(0);
    }
}

避坑指南

  1. 循環引用:組裝時檢測鏈路成環
  2. 請求未被處理:末端節點必須有默認處理邏輯(拒絕/記錄/拋異常)
  3. 線程安全:處理者無狀態則線程安全;有狀態需 ThreadLocal 或請求作用域
  4. 性能:鏈路過長影響響應,關鍵路徑控制在 5-8 節點內

責任鏈模式是流程型業務建模的利器,善用它能讓複雜審批、校驗、過濾邏輯清晰可控。

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