• 【设计模式专题】责任链模式实战讲解


    🍍每日推荐

    🍖文章开始之前我想首先介绍一下牛客,以便没有使用过的小伙伴能够快速入手,牛客网是国内最大的算法、面试、招聘网站,涵盖了多种大厂面试真题以及题解,里面大佬云集,各种题目的解决方案层出不穷,绝对能让你大开眼界,而且牛客是你在人生中不同的阶段都能对你有所帮助的编程软件(完全免费),如果感兴趣可以访问注册一下

    访问链接:牛客-国内最大的刷题网站

    一 什么是责任链模式

    责任链模式是一种让校验逻辑与业务解耦的一种设计模式,让每个节点都有自己的处理器,处理器去处理具体逻辑,并且每个节点都有对下一个节点的引用,类似于没有prev的单向链表,当前节点指向下一个节点。

    当调用方法时,沿着预定的链路依次对每个节点进行处理,直到某个节点被终止或整条链路处理完成。

    让调用方法者不用在意方法内的校验逻辑,只需要关注业务逻辑,让业务结构更加清晰。

    二 什么时候使用责任链模式

    比如一次请求,A条件不满足时立马return,B条件不满足时return,C条件不满足时return等等,所有的校验完成后开始进行业务逻辑。
    第一 此时如果又发起了一个其他的请求那么又需要copy一份相同校验代码,完全没有进行复用。

    第二 没有和业务解耦,代码中有60%都是校验代码,40%业务代码,头重脚轻。

    如果我调用一个方法我肯定是不关心他校验的代码,我只关心它的业务代码,所以调用方法时需要观察大量无用代码,那么此时我们就可以使用责任链模式了。

    三 实战

    import lombok.Data;
    /**
     * @Author liuy
     * @Description 用户信息
     * @Date 2022/7/29 17:47
     * @Version 1.0
     */
    @Data
    public class User {
     private String userName;
     private String password;
     private Integer age;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    
    import lombok.Data;
    
    /**
     * 责任链处理器抽象类
     * @param 
     */
    @Data
    public abstract class Handler<T> {
    
        protected Handler next;
    
        //寻找下一个校验节点
        private void next(Handler next) {
            this.next = next;
        }
    
        public abstract void doHandler(User m);
    
        public static class Builder<T> {
            private Handler<T> head;
            private Handler<T> tail;
    
            public Builder<T> addHandler(Handler 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;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    
    import com.ruoyi.common.utils.StringUtils;
    
    /**
     * 登录校验处理器
     */
    public class LoginHandler extends Handler {
    
        @Override
        public void doHandler(User member) {
            if (StringUtils.isEmpty(member.getUserName()) ||
                    StringUtils.isEmpty(member.getPassword())) {
                System.out.println("请填写用户名或密码");
                return;
            }
            if (null != next) {
                next.doHandler(member);
            }
        }
    
    
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    
    /**
     * 年龄校验处理器
     */
    public class AgeHandler extends Handler {
    
        public AgeHandler() {
        }
    
        //建造者模式 再建造一些责任链中某个单位的子链路
        public AgeHandler(Handler.Builder builder) {
            builder.addHandler(new AgeMinHandler())
                   .addHandler(new AgeMaxHandler());
        }
        @Override
        public void doHandler(User member) {
            if (member.getAge() == null || member.getAge() == 0) {
                System.out.println("请填写年龄");
                return;
            }
            if (null != next) {
                next.doHandler(member);
            }
    
        }
    
        public static class AgeMinHandler extends Handler {
    
            @Override
            public void doHandler(User member) {
                if (member.getAge() < 22 ) {
                    System.out.println("还没毕业 不要");
                    return;
                }
                if (null != next) {
                    next.doHandler(member);
                }
    
            }
    
        }
    
        public static class AgeMaxHandler extends Handler {
    
            @Override
            public void doHandler(User member) {
                if (member.getAge() > 35) {
                    System.out.println("年龄太大 不要");
                    return;
                }
                if (null != next) {
                    next.doHandler(member);
                }
            }
        }
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    测试

    /**
     * @Author liuy
     * @Description 测试类
     * @Date 2022/8/3 16:03
     * @Version 1.0
     */
    public class HandlerTest {
        public static void main(String[] args) {
            User member = new User();
            member.setUserName("admin");
            member.setPassword("123");
            member.setAge(36);
            Handler.Builder builder = new Handler.Builder();
            //添加链路节点
            builder.addHandler(new AgeHandler(builder))
            .addHandler(new LoginHandler());
    
            builder.build().doHandler(member);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    结果

    在这里插入图片描述

    我们预设了责任链:LoginHandler——>AgeHandler,那么一个请求就会验证这个责任链一步步往后传递,要么被某个节点return终止,要么直至最后处理完成。

    四、使用案例

    JDK中的Filter,它是一个接口,类似我们的抽象Handler,它的子类实现其中的doFilter方法;

    五、模式总结

    5.1 优点

    将请求和处理进行解耦;请求处理者只关注自己感兴趣的请求进行处理,对于不感兴趣的交给下一个节点处理;
    具备链式传递处理能力,请求发送者不需要知道全局链路,符合迪米特法则(最少只是原则);
    链路结构灵活,可以通过改变链路结构动态地增减责任,符合开闭原则;

    5.2 缺点

    责任链太长或者某个处理节点处理时间过长,会影响整体的性能;
    如果处理节点存在循环引用,会造成死循环;

    🍍每日推荐

    🍖文章开始之前我想首先介绍一下牛客,以便没有使用过的小伙伴能够快速入手,牛客网是国内最大的算法、面试、招聘网站,涵盖了多种大厂面试真题以及题解,里面大佬云集,各种题目的解决方案层出不穷,绝对能让你大开眼界,而且牛客是你在人生中不同的阶段都能对你有所帮助的编程软件(完全免费),如果感兴趣可以访问注册一下

    访问链接:牛客-国内最大的刷题网站

  • 相关阅读:
    移动安全规范 — 2 -蓝牙安全规范
    批量归一化(标准化)处理
    【经典算法】LeetCode 27. 移除元素(Java/C/Python3/Go实现含注释说明,Easy)
    [数据结构] - 顺序表与链表详解
    【C++编程能力提升】
    Spring 事务失效了,怎么办?
    C++模拟题[第一周-T1] 扑克
    适配器模式
    万字爽文一篇带你掌握Java8新特性
    达梦数据库DM8之逻辑导入导出
  • 原文地址:https://blog.csdn.net/weixin_42469135/article/details/126183299