Java责任链模式实战:从基础到建造者优化

Felix
Felix
发布时间:2026-10-15 | 3人浏览过
原创

本文深入解析Java中的责任链模式,针对登录验证等多级处理场景,对比原始臃肿代码与链式结构,提供从基础Handler实现到结合Builder模式自动组装链路的完整重构方案。

什么是责任链模式

责任链模式(Chain of Responsibility)是一种行为型设计模式。它将处理请求的对象连成一条链,请求沿着链传递,直到其中一个对象处理它或到达链条末尾。这种模式的核心优势在于解耦:请求的发送者无需知道具体的接收者是谁,每个节点只需判断自己是否处理,否则将请求传递给下一个节点。

其适用场景主要包括:

  • 多个对象可能处理同一请求,但具体由谁处理在运行时决定。
  • 不明确指定接收者的情况下,向一组对象提交请求。

根据通用UML图,该模式主要包含以下角色:

  • 抽象处理者(Handler):定义处理请求的接口,并维护后继节点的引用。
  • 具体处理者(Concrete Handler):实现具体逻辑,若无法处理则转发给下一节点。

应用场景:以登录流程为例

在开发管理系统时,常见的登录流程通常包含多步校验:检查参数是否为空、查询数据库验证身份、检查用户权限等。若不使用设计模式,这些逻辑往往堆砌在同一个方法中,导致代码耦合度高,违反开闭原则。

未优化前的代码问题

传统的写法是将所有判断逻辑写在一个方法里,如下所示。随着业务增长,该方法会越来越长,修改某一步骤可能需要影响整个函数,且难以测试单个校验环节。

private String login(String username, String password) {
    if (username == null || password == null) {
        return "账户或者密码为null";
    }
    User user = queryUserInfo(username, password);
    if (user == null) {
        return "找不到用户";
    }
    if (!Objects.equals(user.getRoleName(), "超管")) {
        return "没有权限";
    }
    return "登录成功";
}

private User queryUserInfo(String username, String password) {
    if (Objects.equals(username, "土豆") && Objects.equals(password, "666666")) {
        return new User(username, password, "超管");
    } else if (Objects.equals(username, "土豆2号") && Objects.equals(password, "666666")) {
        return new User(username, password, "普通员工");
    }
    return null;
}

采用基础责任链模式重构

我们将不同的校验逻辑拆分为独立的“节点”,并通过 setNext 方法手动连接它们。

  • 定义抽象处理者:声明 doHandler 接口和设置下一个节点的 setNext 方法。
  • public abstract class Handler {
        protected Handler next;
    
        public void setNext(Handler next) {
            this.next = next;
        }
    
        public abstract void doHandler(User user);
    }
  • 实现具体节点:每个类继承 Handler,实现自己的校验逻辑,并在符合条件或校验通过后调用 this.next.doHandler(user)。
  • public class ValidatedHandler extends Handler {
        @Override
        public void doHandler(User user) {
            if (user.getUsername() == null || user.getPassword() == null) {
                System.out.println("账户或者密码为null");
            } else {
                this.next.doHandler(user);
            }
        }
    }
    
    public class UserHandler extends Handler {
        @Override
        public void doHandler(User user) {
            // 模拟查询用户信息并填充角色
            queryUserInfo(user);
            if (user.getRoleName() == null) {
                System.out.println("没有找到用户");
            } else {
                this.next.doHandler(user);
            }
        }
    
        private static void queryUserInfo(User user) {
            if (Objects.equals(user.getUsername(), "土豆") && Objects.equals(user.getPassword(), "666666")) {
                user.setRoleName("超管");
            } else if (Objects.equals(user.getUsername(), "土豆2号") && Objects.equals(user.getPassword(), "666666")) {
                user.setRoleName("普通员工");
            }
        }
    }
    
    public class AuthHandler extends Handler {
        @Override
        public void doHandler(User user) {
            if (!Objects.equals(user.getRoleName(), "超管")) {
                System.out.println("没有权限");
            } else {
                System.out.println("登入成功");
            }
        }
    }
  • 组装并执行链条:在调用层依次连接各处理器。
  • User user = new User("土豆", "666666");
    Handler validatedHandler = new ValidatedHandler();
    Handler userHandler = new UserHandler();
    Handler authHandler = new AuthHandler();
    
    // 手动连接链
    validatedHandler.setNext(userHandler);
    userHandler.setNext(authHandler);
    
    // 开始执行
    validatedHandler.doHandler(user); 

    上述 UML 图展示了使用 Builder 模式优化后的链式结构关系,此时装配逻辑被封装,调用者不再需要关心内部连接细节。

    进阶:结合 Builder 模式自动化组装

    虽然基础版实现了职责分离,但每次新增处理步骤都需要在调用端修改 setNext 逻辑。利用 Builder 模式可以在处理者内部自动维护链表组装,使代码更简洁。

    修改 Handler 抽象类,加入内部 Builder:

    public abstract class Handler {
        protected Handler next;
    
        public void setNext(Handler next) {
            this.next = next;
        }
    
        public abstract void doHandler(User user);
    
        /**
         * 引入 Builder 自动构建链路
         */
        public static class Builder {
            private Handler head; // 头节点
            private Handler tail; // 尾节点
    
            /**
             * 添加处理节点
             */
            public Builder addHandler(Handler handler) {
                if (this.head == null) {
                    this.head = this.tail = handler;
                } else {
                    this.tail.setNext(handler);
                    this.tail = handler;
                }
                return this;
            }
    
            /**
             * 返回头节点,触发执行
             */
            public Handler build() {
                return this.head;
            }
        }
    }

    调用方式简化为链式调用:

    User user = new User("土豆", "666666");
    Handler handler = new Handler.Builder()
            .addHandler(new ValidatedHandler())
            .addHandler(new UserHandler())
            .addHandler(new AuthHandler())
            .build(); // 获取链的头节点
    handler.doHandler(user); // 统一入口发起请求

    优缺点分析

    优点:

    • 降低耦合度: 请求方只需将请求发出,无需知道哪些对象参与了处理。
    • 单一职责: 每个节点只关注自己的业务逻辑。
    • 符合开闭原则: 可以通过灵活增加或删除节点来改变系统行为,无需修改现有代码。

    缺点:

    • 性能损耗: 如果链条过长,或者存在复杂的循环引用,可能会影响性能。
    • 追踪困难: 调试时较难定位请求在哪个节点中断或失败。

    以上就是Java责任链模式从基础应用到高级优化的详细内容,更多关于Java设计模式的学习资料请关注本站其它相关文章!

    相关标签:

    本站声明

    本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

    Python 相关产品和应用

    全部下载

    专题列表