Java设计模式(十六)行为型- 职责链模式chain of responsibility pattern(史上最全职责链模式)与使用场景以及优缺点

1.职责链模式chain of responsibility pattern

职责链模式是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。

职责链模式主要包含以下角色:

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1.1 代码实现

下面以一个简单的登录校验流程来通过代码进行实现:

// 用户实体类
@Data
public class User {
    private String username;
    private String password;
    private String role;
}
// handler抽象类
public abstract class Handler {
    protected Handler next;
    // 返回handler方便链式操作
    public void next(Handler next) {
        this.next = next;
    }
    // 流程开始的方法
    public abstract void doHandler(User user);
}
// 校验用户名或者密码是否为空
public class ValidateHandler extends Handler {
    @Override
    public void doHandler(User user) {
        if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) {
            System.out.println("用户名或者密码为空!");
            return;
        }
        System.out.println("校验通过");
        next.doHandler(user);
    }
}
// 登录校验,校验用户名是否匹配密码
public class LoginHandler extends Handler {
    @Override
    public void doHandler(User user) {
        if (!"pyy52hz".equals(user.getUsername()) || !"123456".equals(user.getPassword())) {
            System.out.println("用户名或者密码不正确!请检查!");
            return;
        }
        user.setRole("admin");
        System.out.println("登陆成功!角色为管理员!");
        next.doHandler(user);
    }
}
// 权限校验
public class AuthHandler extends Handler {
    @Override
    public void doHandler(User user) {
        if (!"admin".equals(user.getRole())) {
            System.out.println("无权限操作!");
            return;
        }
        System.out.println("角色为管理员,可以进行下一步操作!");
    }
}
// 登录流程
public class LoginService {
    public void login(User user) {
        Handler validateHandler = new ValidateHandler();
        Handler loginHandler = new LoginHandler();
        Handler authHandler = new AuthHandler();
        validateHandler.next(loginHandler);
        loginHandler.next(authHandler);
        validateHandler.doHandler(user);
    }
}
    // 测试方法
    public static void main(String[] args){
      User user = new User();
      //校验通过
      //用户名或者密码不正确!请检查!
      user.setUsername("pyy52hz");
      user.setPassword("1234567");
      LoginService loginService = new LoginService();
      loginService.login(user);
      //校验通过
      //登陆成功!角色为管理员!
      //角色为管理员,可以进行下一步操作!
      user.setUsername("pyy52hz");
      user.setPassword("123456");
      loginService.login(user);
    }

1.3 结合建造者模式

与基础版本区别主要是Handler类中新增一个Builder的内部类,以及流程类里改用链式写法,具体如下:

// handler抽象类
public abstract class Handler<T> {
    protected Handler next;
    // 返回handler方便链式操作
    public Handler next(Handler next) {
        this.next = next;
        return next;
    }
    // 流程开始的方法
    public abstract void doHandler(User user);
    static class Builder<T> {
        private Handler<T> head;
        private Handler<T> tail;
        public Builder<T> addHandler(Handler<T> handler) {
            if (this.head == null) {
                this.head = this.tail = handler;
                return this;
            }
            this.tail.next(handler);
            this.tail = handler;
            return this;
        }
        public Handler<T> build() {
            return this.head;
        }
    }
}
public class LoginService {
    public void login(User user) {
        Handler.Builder builder = new Handler.Builder();
        builder.addHandler(new ValidateHandler())
            .addHandler(new LoginHandler())
            .addHandler(new AuthHandler());
        builder.build().doHandler(user);
    }
}

1.4 总结

适用场景:

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

优点:

  • 将请求与处理解耦。
  • 请求处理者(节点对象)只需关注自己感兴趣的请求进行处理即可,对于不感兴> - 趣的请求,直接转发给下一级节点对象。
  • 具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果。
  • 链路结构灵活,可以通过改变链路结构动态地新增或删减责任。
  • 易于扩展新的请求处理类(节点),符合开闭原则。

缺点:

  • 责任链太长或者处理时间过长,会影响整体性能。
  • 如果节点对象存在循环引用时,会造成死循环,导致系统崩溃。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘了个刘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值