设计模式之责任链模式(Java实现)

举报
长路 发表于 2022/11/28 18:18:16 2022/11/28
【摘要】 文章目录前言一、认识责任链模式二、实现责任链模式总结参考资料 前言 本篇博客是关于责任链方法模式的实现,若文章中出现相关问题,请指出! 对应代码地址:Gitee(demo-exer/ java-Lear23designpatterns)、Github(java-demo/ java-Lear23designpatterns) 所有博客文件目录索引:博客目录索引(持续更新) 一、认识责任链模式 责任

@[toc]

前言

本篇博客是关于责任链方法模式的实现,若文章中出现相关问题,请指出!

对应代码地址:Gitee(demo-exer/ java-Lear23designpatterns)Github(java-demo/ java-Lear23designpatterns)

所有博客文件目录索引:博客目录索引(持续更新)

一、认识责任链模式

责任链模式定义:为请求创建了一个接受者对象的链。为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

  • 该模式又叫职责链模式

结构

  1. 抽象处理者:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  2. 具体处理者:实现抽象处理者的处理方法,该处理方法中会进行判断能够处理本次请求,如果可以则将请求转给其后继者继续执行处理方法。

结构图如下

image-20210320220007633

优缺点

  • 优点:请求的发送者和接受者解耦;可以控制执行顺序;符合开闭原则单一职责原则
  • 缺点:对比较长的职责链,请求处理可能会涉及多个处理对象,性能会受到影响;增加了客户端的复杂性,可能会造成循环调用。

应用场景

  1. Tomcat中的过滤器链使用到了责任链模式,其中ApplicationFilterChain类实现了FilterChain接口,其底层实现使用的是数组,关键方式是doFilter()internalDoFilter()方法。


二、实现责任链模式

该案例是在学习视频案例之后手敲了一下,视频:2020年最详细的23种Java设计模式完整视频教程全集

image-20210320210044309

demo见xyz.changlu.chain包下代码:

image-20210320204530246

请求对象:Request

//实例对象:通过其中属性来判定其中的执行是否有效
public class Request {

    private boolean requestFrequency;//请求频率
    private boolean loginAuthentication;//登陆认证
    private boolean accessPermission;//访问权限

    public Request(RequestBuilder builder){
        this.requestFrequency = builder.requestFrequency;
        this.loginAuthentication = builder.loginAuthentication;
        this.accessPermission = builder.accessPermission;
    }

    static class RequestBuilder{
        private boolean requestFrequency;//请求频率
        private boolean loginAuthentication;//登陆认证
        private boolean accessPermission;//访问权限

        public RequestBuilder setRequestFrequency(boolean requestFrequency){
            this.requestFrequency = requestFrequency;
            return this;
        }

        public RequestBuilder setLoginAuthentication(boolean loginAuthentication){
            this.loginAuthentication = loginAuthentication;
            return this;
        }

        public RequestBuilder setAccessPermission(boolean accessPermission){
            this.accessPermission = accessPermission;
            return this;
        }

        public Request build(){
            return new Request(this);
        }
    }

    public boolean isRequestFrequency() {
        return requestFrequency;
    }

    public boolean isLoginAuthentication() {
        return loginAuthentication;
    }

    public boolean isAccessPermission() {
        return accessPermission;
    }
}
  • 内部使用到了建造者模式来方便进行赋值操作!

抽象处理者:Handler

//抽象处理者
public abstract class Handler {

    private Handler next;

    public Handler(Handler handler){
        this.next = handler;
    }

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }

    abstract boolean process(Request request);

}
  • 包含了具体方法以及抽象方法,该类实际上是使用链表进行连接的,其抽象方法是留给对应的子类来进行实现其中的执行过程。

具体处理者1:RequestFrequencyHandler

//具体处理者1:请求频率处理器
public class RequestFrequencyHandler extends Handler{

    public RequestFrequencyHandler(Handler handler) {
        super(handler);
    }

    @Override
    boolean process(Request request) {
        System.out.println("开始执行请求频率....");
        //1、判断请求频率是否符合规则
        if(request.isRequestFrequency()){
            System.out.println("执行请求频率正常,通过!");
            Handler handler = this.getNext();
            //表示通过
            if (handler != null) {
                //2、执行其下一个处理器(登陆验证)
                if (!handler.process(request)) {
                    return false;
                }
            }
            return true;
        }
        //请求频率过多失败
        System.out.println("请求频率过多失败!");
        return false;
    }
}

具体处理者2:LoginAuthenticationHandler

//登陆认证处理器
public class LoginAuthenticationHandler extends Handler{

    public LoginAuthenticationHandler(Handler handler) {
        super(handler);
    }

    @Override
    boolean process(Request request) {
        System.out.println("开始执行登陆验证....");
        //1、判断登陆验证是否通过
        if(request.isLoginAuthentication()){
            System.out.println("登陆验证通过!");
            Handler handler = this.getNext();
            //判断是否有下个执行器(本案例无)
            if (handler != null) {
                //2、判断是下个执行器是否通过(本案例是不会执行到这里的)
                if (!handler.process(request)) {
                    return false;
                }
            }
            return true;
        }
        //登陆认证失败
        System.out.println("登陆认证失败!");
        return false;
    }
}
  • 与处理者1大致相同,也包含了执行其关联的下一个执行器。

测试程序:测试类Customer

①测试两个false情况

//测试类
public class Customer {
    public static void main(String[] args) {
        //设置request对象的属性
        Request request = new Request.RequestBuilder().setRequestFrequency(false).setLoginAuthentication(false).build();
        //将登陆认证执行放置到请求频率执行器之后
        RequestFrequencyHandler requestFrequencyHandler = new RequestFrequencyHandler(new LoginAuthenticationHandler(null));
        //开始执行
        requestFrequencyHandler.process(request);
    }
}

image-20210320205541189

②测试两个true请求

image-20210320205620892

说明:可以看到按照设置执行器顺序依次执行下去(就像一个链条一样),一旦有个执行方法不通过则会直接结束。



总结

责任链模式通常使用于如处理的是单个请求需要有多个请求处理者来处理不同的事情,将多个处理者链接起来。处理者可通过继承一个抽象类来实现其中的处理方法,并且若是其中情况成立可执行下一个请求处理者,形成一个执行链。



参考资料

视频:2020年最详细的23种Java设计模式完整视频教程全集

[1]. 从Tomcat中学习责任链模式

[2]. 责任链模式(职责链模式)详解

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。