小易说IT 小易说IT

Java 责任链模式(Chain of Responsibility)示例代码

责任链模式:将请求沿着处理者链进行传递,每个处理者判断是否处理该请求;可以处理则执行,否则交给下一个处理器,请求发送方不需要知道谁最终处理请求

适用场景:权限校验、审批流程、过滤器、日志级别处理、表单校验等。

场景模拟

模拟请假审批

  • 组长:审批 ≤3 天假期

  • 部门经理:审批 3‑7 天假期

  • 总经理:审批 7‑30 天假期 超过 30 天不允许请假。

1. 请求实体 LeaveRequest

/**
 * 请假请求对象
 */
public class LeaveRequest {
    /** 请假人 */
    private String name;
    /** 请假天数 */
    private int days;

    public LeaveRequest(String name, int days) {
        this.name = name;
        this.days = days;
    }

    public String getName() {
        return name;
    }

    public int getDays() {
        return days;
    }
}

2. 抽象处理器 Handler

/**
 * 抽象审批处理器
 */
public abstract class Handler {
    // 下一个处理器
    protected Handler nextHandler;

    /**
     * 设置下一个处理器
     */
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 处理请假请求
     */
    public abstract void handleRequest(LeaveRequest request);
}

3. 具体处理器实现

组长 Handler

/**
 * 组长:最多审批3天
 */
public class GroupLeaderHandler extends Handler {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getDays() <= 3) {
            System.out.printf("【组长】审批通过:%s 请假 %d 天%n", request.getName(), request.getDays());
        } else {
            // 交给下一位
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("无人可以处理该请假申请");
            }
        }
    }
}

部门经理 Handler

/**
 * 部门经理:3~7天
 */
public class DeptManagerHandler extends Handler {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getDays() > 3 && request.getDays() <=7) {
            System.out.printf("【部门经理】审批通过:%s 请假 %d 天%n", request.getName(), request.getDays());
        } else {
            if(nextHandler != null){
                nextHandler.handleRequest(request);
            }else{
                System.out.println("无人可以处理该请假申请");
            }
        }
    }
}

总经理 Handler

/**
 * 总经理:7~30天
 */
public class GeneralManagerHandler extends Handler {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getDays() >7 && request.getDays() <=30) {
            System.out.printf("【总经理】审批通过:%s 请假 %d 天%n", request.getName(), request.getDays());
        } else {
            System.out.printf("【总经理】拒绝申请:%s,请假%d天超过最大限制%n", request.getName(), request.getDays());
        }
    }
}

4. 客户端测试代码

public class Client {
    public static void main(String[] args) {
        // 1. 构建责任链:组长 -> 部门经理 -> 总经理
        Handler groupLeader = new GroupLeaderHandler();
        Handler deptManager = new DeptManagerHandler();
        Handler generalManager = new GeneralManagerHandler();

        groupLeader.setNextHandler(deptManager);
        deptManager.setNextHandler(generalManager);

        // 发起不同请假请求
        LeaveRequest req1 = new LeaveRequest("张三", 2);
        LeaveRequest req2 = new LeaveRequest("李四", 5);
        LeaveRequest req3 = new LeaveRequest("王五", 15);
        LeaveRequest req4 = new LeaveRequest("赵六", 40);

        System.out.println("=====请求1=====");
        groupLeader.handleRequest(req1);

        System.out.println("=====请求2=====");
        groupLeader.handleRequest(req2);

        System.out.println("=====请求3=====");
        groupLeader.handleRequest(req3);

        System.out.println("=====请求4=====");
        groupLeader.handleRequest(req4);
    }
}

输出结果

=====请求1=====
【组长】审批通过:张三 请假 2 天
=====请求2=====
【部门经理】审批通过:李四 请假 5 天
=====请求3=====
【总经理】审批通过:王五 请假 15 天
=====请求4=====
【总经理】拒绝申请:赵六,请假40天超过最大限制

责任链变体:Spring Filter / Servlet Filter 风格

真实项目中经常使用链式 + 上下文,处理器可以选择继续执行链 chain.doFilter(),也可以中断。

// 请求上下文
class Context {
    private String msg;
    public Context(String msg) { this.msg = msg; }
    public String getMsg() { return msg; }
}

/**
 * 过滤器抽象
 */
interface Filter {
    void doFilter(Context ctx, FilterChain chain);
}

class FilterChain {
    private List<Filter> filters = new ArrayList<>();
    private int index = 0;

    public FilterChain addFilter(Filter filter) {
        filters.add(filter);
        return this;
    }

    public void doFilter(Context ctx) {
        if(index < filters.size()){
            Filter f = filters.get(index++);
            f.doFilter(ctx, this);
        }
    }
}

// 具体过滤器
class AuthFilter implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) {
        System.out.println("权限校验");
        chain.doFilter(ctx); // 继续向下;不调用则中断链
    }
}

class LogFilter implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) {
        System.out.println("日志记录");
        chain.doFilter(ctx);
    }
}

// 测试
class FilterClient {
    public static void main(String[] args) {
        FilterChain chain = new FilterChain();
        chain.addFilter(new AuthFilter())
             .addFilter(new LogFilter());
        chain.doFilter(new Context("test"));
    }
}

输出:

权限校验
日志记录

模式要点总结

优点

  1. 请求与处理解耦,客户端不用关心谁处理;

  2. 处理器灵活组合,动态增删、调换顺序;

  3. 符合开闭原则,新增处理器不用修改旧代码。

缺点

  1. 请求可能没有对象处理;

  2. 链过长会带来性能损耗;

  3. 调试不方便。

🎯 常见使用场景

  • Servlet Filter、Spring Interceptor

  • 多级审批流

  • 参数校验、风控规则链

  • 日志级别处理


本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/java-chain-of-responsibility-pattern-example-code

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/