责任链模式

简介

定义: 为请求创建一个接收者对象的链,沿着链传递请求直到有对象处理它。

使用场景:

  • 请假审批流程

  • 异常处理链

  • Servlet过滤器链

  • Spring Security过滤器

实现要点:

  • 每个处理器持有下一个处理器引用

  • 链式调用

  • 可以动态组合

UML

代码示例

  1. 抽象审批处理器

public abstract class ApprovalHandler {
    
    /**
     * 下一个处理器
     */
    protected ApprovalHandler nextHandler;
    
    /**
     * 设置下一个处理器
     */
    public void setNext(ApprovalHandler handler) {
        this.nextHandler = handler;
    }
    
    /**
     * 处理请求
     */
    public final ApprovalResult handle(LeaveRequest request) {
        // 当前处理器处理请求
        ApprovalResult result = doHandle(request);
        
        // 如果当前处理器无法处理或拒绝,则传递给下一个处理器
        if (nextHandler != null && (!result.isApproved() || !canHandle(request))) {
            result = nextHandler.handle(request);
        }
        
        return result;
    }
    
    /**
     * 具体的处理逻辑,由子类实现
     */
    protected abstract ApprovalResult doHandle(LeaveRequest request);
    
    /**
     * 判断当前处理器是否可以处理该请求
     */
    protected abstract boolean canHandle(LeaveRequest request);
    
    /**
     * 获取处理器名称
     */
    protected abstract String getHandlerName();
}
  1. 各个处理器

/**
 * @author dcx
 * @description 董事会处理器 - 处理超长请假申请
 * @create 2025-01-27
 */
public class BoardHandler extends ApprovalHandler {

    @Override
    protected ApprovalResult doHandle(LeaveRequest request) {
        if (request.getLeaveDays() <= 90) {
            return ApprovalResult.approved(getHandlerName(), 
                String.format("董事会批准%s的%d天请假申请", request.getEmployeeName(), request.getLeaveDays()));
        } else {
            return ApprovalResult.rejected(getHandlerName(), 
                String.format("请假天数超过90天,建议办理停薪留职"));
        }
    }

    @Override
    protected boolean canHandle(LeaveRequest request) {
        return true; // 董事会是最高级别,可以处理所有请求
    }

    @Override
    protected String getHandlerName() {
        return "董事会";
    }
}
/**
 * @author dcx
 * @description 部门经理处理器 - 可以审批7天以内的请假
 * @create 2025-01-27
 */
public class DepartmentManagerHandler extends ApprovalHandler {

    @Override
    protected ApprovalResult doHandle(LeaveRequest request) {
        if (request.getLeaveDays() <= 7) {
            return ApprovalResult.approved(getHandlerName(), 
                String.format("部门经理批准%s的%d天请假申请", request.getEmployeeName(), request.getLeaveDays()));
        } else {
            return ApprovalResult.rejected(getHandlerName(), 
                String.format("请假天数超过7天,需要总经理审批"));
        }
    }

    @Override
    protected boolean canHandle(LeaveRequest request) {
        return request.getLeaveDays() <= 7;
    }

    @Override
    protected String getHandlerName() {
        return "部门经理";
    }
}
/**
 * @author dcx
 * @description 总经理处理器 - 可以审批任意天数的请假
 * @create 2025-01-27
 */
public class GeneralManagerHandler extends ApprovalHandler {

    @Override
    protected ApprovalResult doHandle(LeaveRequest request) {
        if (request.getLeaveDays() <= 30) {
            return ApprovalResult.approved(getHandlerName(), 
                String.format("总经理批准%s的%d天请假申请", request.getEmployeeName(), request.getLeaveDays()));
        } else {
            return ApprovalResult.rejected(getHandlerName(), 
                String.format("请假天数超过30天,需要董事会决议"));
        }
    }

    @Override
    protected boolean canHandle(LeaveRequest request) {
        return request.getLeaveDays() <= 30;
    }

    @Override
    protected String getHandlerName() {
        return "总经理";
    }
}
/**
 * @author dcx
 * @description 团队负责人处理器 - 可以审批3天以内的请假
 * @create 2025-01-27
 */
public class TeamLeaderHandler extends ApprovalHandler {

    @Override
    protected ApprovalResult doHandle(LeaveRequest request) {
        if (request.getLeaveDays() <= 3) {
            return ApprovalResult.approved(getHandlerName(), 
                String.format("团队负责人批准%s的%d天请假申请", request.getEmployeeName(), request.getLeaveDays()));
        } else {
            return ApprovalResult.rejected(getHandlerName(), 
                String.format("请假天数超过3天,需要上级审批"));
        }
    }

    @Override
    protected boolean canHandle(LeaveRequest request) {
        return request.getLeaveDays() <= 3;
    }

    @Override
    protected String getHandlerName() {
        return "团队负责人";
    }
}
  1. 请求和响应体

@Data
public class LeaveRequest {
    /**
     * 员工姓名
     */
    private String employeeName;
    
    /**
     * 请假天数
     */
    private int leaveDays;
    
    /**
     * 请假原因
     */
    private String reason;

    public LeaveRequest(String employeeName, int leaveDays, String reason) {
        this.employeeName = employeeName;
        this.leaveDays = leaveDays;
        this.reason = reason;
    }

    @Override
    public String toString() {
        return String.format("员工: %s, 请假天数: %d, 请假原因: %s", 
                           employeeName, leaveDays, reason);
    }
}

@Data
public class ApprovalResult {
    /**
     * 是否通过
     */
    private boolean approved;
    
    /**
     * 审批人
     */
    private String approver;
    
    /**
     * 审批意见
     */
    private String comment;

    public ApprovalResult(boolean approved, String approver, String comment) {
        this.approved = approved;
        this.approver = approver;
        this.comment = comment;
    }

    public static ApprovalResult approved(String approver, String comment) {
        return new ApprovalResult(true, approver, comment);
    }

    public static ApprovalResult rejected(String approver, String comment) {
        return new ApprovalResult(false, approver, comment);
    }

    @Override
    public String toString() {
        return String.format("审批结果: %s, 审批人: %s, 意见: %s", 
                           approved ? "通过" : "拒绝", approver, comment);
    }
}
  1. 使用方式

public class Test {

    public static void main(String[] args) {
        // 创建责任链
        ApprovalHandler teamLeader = new TeamLeaderHandler();
        ApprovalHandler departmentManager = new DepartmentManagerHandler();
        ApprovalHandler generalManager = new GeneralManagerHandler();
        ApprovalHandler board = new BoardHandler();

        // 设置责任链的顺序:团队负责人 -> 部门经理 -> 总经理 -> 董事会
        teamLeader.setNext(departmentManager);
        departmentManager.setNext(generalManager);
        generalManager.setNext(board);

        // 创建测试用例
        LeaveRequest[] testCases = {
            new LeaveRequest("张三", 2, "感冒发烧"),
            new LeaveRequest("李四", 5, "家里有事"),
            new LeaveRequest("王五", 10, "旅游度假"),
            new LeaveRequest("赵六", 25, "探亲访友"),
            new LeaveRequest("钱七", 60, "长期病假"),
            new LeaveRequest("孙八", 120, "创业准备")
        };

        System.out.println("=== 责任链模式 - 请假审批系统 ===\n");

        // 测试各种请假申请
        for (LeaveRequest request : testCases) {
            System.out.println("提交申请: " + request);
            ApprovalResult result = teamLeader.handle(request);
            System.out.println("审批结果: " + result);
            System.out.println("----------------------------------------");
        }

        System.out.println("\n=== 责任链模式说明 ===");
        System.out.println("1. 团队负责人: 可审批3天以内");
        System.out.println("2. 部门经理: 可审批7天以内");
        System.out.println("3. 总经理: 可审批30天以内");
        System.out.println("4. 董事会: 可审批90天以内");
        System.out.println("5. 超过90天: 建议停薪留职");
    }
}

Last updated

Was this helpful?