首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【设计模式精解】Java实现责任链模式(职责链模式)优雅处理多级请求(概述,使用场景,优缺点,代码示例)

【设计模式精解】Java实现责任链模式(职责链模式)优雅处理多级请求(概述,使用场景,优缺点,代码示例)

作者头像
程序员三明治
发布2025-12-18 20:16:10
发布2025-12-18 20:16:10
1730
举报
文章被收录于专栏:码力up码力up

责任链模式是什么?

责任链设计模式是一种行为型设计模式,其主要目的是解耦请求发送者和请求接收者,让多个对象都有机会处理请求。

在责任链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条,链条上的每个处理器各自承担各自的处理职责。

责任链模式优缺点?

优点在于,它可以动态地添加、删除和调整处理者对象,从而灵活地构建处理链。同时,它也避免了请求发送者和接收者之间的紧耦合。 责任链模式也有一定的缺点,例如如果处理链过长或者处理时间过长,可能会对系统性能产生一定的影响。

责任链模式应用场景?

责任链模式常用于请求的预处理、请求的过滤等场景。例如,可以使用责任链模式来实现前置校验、日志记录等功能。

举例证明责任链模式

例子:小菜想要加薪,需要先向经理申请,如果经理没权利,就向总监上报,总监也没权限,向总经理上报。

不用责任链模式的朴素写法

代码语言:javascript
复制
// 申请
public class Request {
    private String requestType;
    private String requestContent;
    private int number;

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public void setRequestContent(String requestContent) {
        this.requestContent = requestContent;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}

// 管理者
public class Manager {
    private String name;

    public Manager(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void handleRequest(String managerLevel, Request request) {
        if (managerLevel.equals("经理")) {
            if (request.getRequestType().equals("请假")) {
                System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");
                System.out.println("审批人" + this.name);
            } else if (request.getRequestType().equals("加薪")) {
                System.out.println("经理无权处理");
            }
        } else if (managerLevel.equals("总监")) {
            if (request.getRequestType().equals("请假")) {
                System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");
                System.out.println("审批人" + this.name);
            } else if (request.getRequestType().equals("加薪")) {
                System.out.println("总监无权处理");
            }
        } else if (managerLevel.equals("总经理")) {
            if (request.getRequestType().equals("请假")) {
                System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");
                System.out.println("审批人" + this.name);
            } else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {
                System.out.println("员工" + request.getRequestContent() + "请求" + request.getNumber() + "元加薪");
                System.out.println("审批人" + this.name);
            } else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {
                System.out.println("再说吧!");
            }
        }
    }
}

客户端程序

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
        Manager jingli = new Manager("经理");
        Manager zongjian = new Manager("总监");
        Manager zongjingli = new Manager("总经理");

        Request request = new Request();
        request.setRequestType("加薪");
        request.setRequestContent("小菜请求加薪");
        request.setNumber(500);

        jingli.handleRequest("经理", request);
        zongjian.handleRequest("总监", request);
        zongjingli.handleRequest("总经理", request);

        System.out.println("-------------------------------------------------------");

        // 请假
        request.setRequestType("请假");
        request.setRequestContent("小菜请求请假");
        request.setNumber(5);
        jingli.handleRequest("经理", request);
        zongjian.handleRequest("总监", request);
        zongjingli.handleRequest("总经理", request);
    }
}

测试结果

可以看到,上面的代码,类有太多的责任,违背了单一职责原则,增加新的管理类别,需要修改这个类,违背开闭原则,所以我们需要用责任链模式去重构它

责任链模式重构

UML结构图
代码
代码语言:javascript
复制
// 处理者
public abstract class Handler {
    private Handler nextHandler;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Handler getNextHandler() {
        return nextHandler;
    }

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public Handler(String name) {
        this.name = name;
    }

    public abstract void handleRequest(Request request);
}

// 经理处理器
public class JingliHandler extends Handler {

    public JingliHandler(String name) {
        super(name);
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getRequestType().equals("请假")) {
            System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");
            System.out.println("审批人" + this.getName());
        } else if (request.getRequestType().equals("加薪")) {
            System.out.println("员工" + request.getRequestContent() + request.getNumber() + "元加薪");
            System.out.println(this.getName() + "无权处理,交给上级");
            this.getNextHandler().handleRequest(request);
        }
    }
}

// 总监处理器
public class ZongjianHandler extends Handler{

    public ZongjianHandler(String name) {
        super(name);
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getRequestType().equals("请假")) {
            System.out.println("审批人" + this.getName());
        } else if (request.getRequestType().equals("加薪")) {
            System.out.println(this.getName() + "无权处理,交给上级");
            this.getNextHandler().handleRequest(request);
        }
    }
}

// 总经理处理器
public class ZongjingliHandler extends Handler{


    public ZongjingliHandler(String name) {
        super(name);
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getRequestType().equals("请假")) {
            System.out.println("审批人" + this.getName());
        } else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {
            System.out.println("审批人" + this.getName());
        } else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {
            System.out.println("再说吧!!");
        }
    }
}

客户端程序

代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
        JingliHandler jingli = new JingliHandler("经理");
        ZongjianHandler zongjian = new ZongjianHandler("总监");
        ZongjingliHandler zongjingli = new ZongjingliHandler("总经理");
        jingli.setNextHandler(zongjian);
        zongjian.setNextHandler(zongjingli);

        Request request = new Request();
        request.setRequestType("加薪");
        request.setRequestContent("小菜请求加薪");
        request.setNumber(500);

        jingli.handleRequest(request);

        System.out.println("-------------------------------------------------------");

        // 请假
        request.setRequestType("请假");
        request.setRequestContent("小菜请求请假");
        request.setNumber(5);
        jingli.handleRequest(request);
    }
}

测试结果

image.png
image.png

如果经理可以处理的话,直接返回,如果不可以,就交给上级去处理。

哪些源码里用过责任链模式?

之前在看 Mybatis 3.4.x 源码时了解到 Interceptor 底层实现就是责任链模式。 开门见山,直接把视线聚焦到 Mybatis 源码,版本号 3.4.7-SNAPSHOT。

和我们上面用到的责任链模式差不太多,有处理器集合 interceptors,有添加处理器方法。

Mybatis 查询 SQL 的分页语句就是使用 Interceptor 实现,比如市场上的 PageHelper、Mybatis-Plus 分页插件再或者我们自实现的分页插件。

拿查询语句举例,如果定义了多个查询相关的拦截器,会先经过拦截器的代码加工,所有的拦截器执行完毕后才会走真正查询数据库操作。

如果我的内容对你有帮助,请辛苦动动您的手指为我点赞,评论,收藏。感谢大家!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 责任链模式是什么?
  • 责任链模式优缺点?
  • 责任链模式应用场景?
  • 举例证明责任链模式
    • 不用责任链模式的朴素写法
    • 责任链模式重构
      • UML结构图
      • 代码
  • 哪些源码里用过责任链模式?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档