首页 > 编程语言 >我的Java设计模式-责任链模式

我的Java设计模式-责任链模式

时间:2023-02-05 21:13:38浏览次数:53  
标签:Java 请求 处理 子类 模式 boss 责任 设计模式 public

今天来说说程序员小猿和产品就关于需求发生的故事。前不久,小猿收到了产品的需求。

产品经理:小猿,为了迎合大众屌丝用户的口味,我们要放一张图,要露点的。

小猿:......露点?你大爷的,让身为正义与纯洁化身的我做这种需求,还露点。

产品经理:误会误会,是放一张暴露一点点的,尺寸不大。

小猿:尼玛~能说清楚些吗,需求模棱两可的。不干,我要上报boss。

产品经理也一阵无语,这豆丁的事还上报boss。话说这上报也得走程序是吧,技术经理就不干了,“凭什么要跳过我,得经过我才能到boss”。咦~这一层一层上报就涉及到这次的责任链模式

一、责任链模式

定义

  创建多个对象,使这些对象形成一条链,并沿着这条链传递请求,直到链上的某一个对象决定处理此请求。

特点

1)接收请求的对象连接成一条链,对象之间存在层级关系。

2)这些对象可处理请求,也可传递请求,直到有对象处理该请求。

UML

责任链模式UML图.png
责任链模式UML图.png

责任链模式涉及到的角色如下所示:

  - 抽象处理者角色:定义了处理请求的接口或者抽象类,提供了处理请求的的方法和设置下一个处理者的方法。

  - 具体处理者角色:实现或者继承抽象这角色,具体逻辑根据实际的架构来定,后面会提到。

二、实战

先来看抽象处理者角色代码:

public abstract class Handler {
    private Handler nextHandler;
    private int level;
    public Handler(int level) {
        this.level = level;
    }

    // 处理请求传递,注意final,子类不可重写
    public final void handleMessage(Demand demand) {
        if (level == demand.demandLevel()) {
            this.report(demand);
        } else {
            if (this.nextHandler != null) {
                System.out.println("事情太严重,需报告上一级");
                this.nextHandler.handleMessage(demand);
            } else {
                System.out.println("我就是boss,没有上头");
            }
        }
    }

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

    // 抽象方法,子类实现
    public abstract void report(Demand demand);
}复制代码

在抽象处理者角色定义了处理请求的抽象方法,以及下一级传递的对象方法,重点在handleMessage处理请求传递的方法,下面会解释为什么要这样写,继续往下看。

下面是具体处理者角色,继承抽象处理者角色,在我们情景中有两个具体处理者,分别是技术经理和boss。

// 技术经理
public class TechnicalManager extends Handler {
    public TechnicalManager() {
        super(1);
    }

    @Override
    public void report(Demand demand) {
        System.out.println("需求:" + demand.detail());
        System.out.println(getClass().getSimpleName() + ":小猿我挺你,这个需求不干");
    }
}

// boss
public class Boss extends Handler {
    public Boss() {
        super(2);
    }

    @Override
    public void report(Demand demand) {
        System.out.println("需求:" + demand.detail());
        System.out.println(getClass().getSimpleName() + ":你们打一架吧,打赢的做决定");
    }
}复制代码

可以看到具体处理者的代码很简洁,重写了report方法,实现各自的业务逻辑,这都归功于父类中handleMessage这个方法。

两个角色都定义好了,来看客户端如何实现:

public class Client {
    public static void main(String[] args) {
        Demand demandA = new DemandA(); // 请求等级低
        Demand demandB = new DemandB(); // 请求等级高

        Boss boss = new Boss();
        TechnicalManager technicalManager = new TechnicalManager();
        technicalManager.setNextHandler(boss); // 设置下一级

        technicalManager.handleMessage(demandA);
        System.out.println("============================");
        technicalManager.handleMessage(demandB);
    }
}复制代码

可以看到在客户端中的重点是设置下一级的处理者,这样多个处理者对象就会形成一条链。运行客户端,结果如下:

需求:加一张露一点点的图
TechnicalManager:小猿我挺你,这个需求不干

============================
需求:加一张露一点点的图
TechnicalManager:事情太严重,需报告上一级
Boss:你们打一架吧,打赢的做决定

从结果可以看到,级别低的请求技术经理自己处理,级别高的传递给了下一级的Boss,这样就形成一条链,而这也是责任链的核心所在。注意,在请求的传递过程中,请求是不会发生变化的。需求不会从“加一张露一点点的图”变成了“加一张露点的图”,这等着boss请到办公室喝茶吧。

三、扩展

责任链+模板方法

回头看看上面的代码,抽象类中定义了几个方法,一个是final修饰的handleMessage,一个是抽象方法report,还有一个是setNextHandler。这刚好是模板方法模式中的三个基本方法,分别是具体方法(抽象类声明并实现,子类不实现)、抽象方法(抽象类声明,子类必须实现)、钩子方法(抽象类声明并实现,子类可扩展)。handleMessage方法加了final修饰,子类不可重写,而handleMessage正是把传递请求工作交给父类Handler,子类不需要处理传递的工作。而report则是抽象方法,子类必须重写该方法,子类处理请求的业务逻辑。setNextHandler是钩子方法,在这里我们并没有实现。

这样结合模板方法模式的好处在哪?首先加了handleMessage方法,把请求的传递判断从子类中剥离出来,让子类在report方法中专心处理请求的业务逻辑,做到了单一职责原则。再者是子类的实现变得简单了,不需要进行传递的判断,非常有利于快速扩展。

责任链模式VS观察者模式

观察者模式我在之前有写过,不了解的可以先看看。责任链模式和观察者模式存在一个共同点,就是传递责任链模式是一级一级的传递,形成一条链,链节点(处理者)之间是存在传递关系的。而观察者模式的被观察者向观察者们的传递,并不是具体观察者之间的传递,观察者之间是不存在关联的。拿小猿的经历来说,在责任链模式中是请求从技术经理到boss,有层级关系,而对于观察者模式是从被观察者小猿发出,作为观察者的技术经理和boss都会收到小猿的通知,是扩散式的,技术经理和boss并没有层级关系。这是责任链模式和观察者模式的区别,也是责任链模式的核心。

四、责任链模式的优缺点

优点

1)降低耦合度:客户端不需要知道请求由哪个处理者处理,而处理者也不需要知道处理者之间的传递关系,由系统灵活的组织和分配。

2)良好的扩展性:增加处理者的实现很简单,只需重写处理请求业务逻辑的方法。

缺点

1)请求会从链头发出,直到有处理者响应,在责任链比较长的时候会影响系统性能。

2)请求递归,调试排错比较麻烦。

总结

责任链模式在实际项目中可以用到的地方还是比较多的,比如会员等级系统,会员等级之间构成一条链,用户发起一个请求,系统只要把请求分发到责任链模式的入口,直到传递到与用户会员匹配的等级,这样各个会员等级的业务逻辑就会变成很清晰。这篇折腾了很久,主要是想把责任链的核心阐述清楚,让大家能够容易理解,也让我重新思考了责任链模式的核心。下一篇是“还没想好”,您的点赞和关注是我的动力哦,再会!

设计模式Java源码GitHub下载https://github.com/jetLee92/DesignPattern

更多精彩文章欢迎关注公众号

AndroidJet的开发之路
AndroidJet的开发之路

来源:https://juejin.cn/post/6844903512506122253

标签:Java,请求,处理,子类,模式,boss,责任,设计模式,public
From: https://www.cnblogs.com/konglxblog/p/17093939.html

相关文章

  • 【JavaScript】3_深挖数据类型
    4、其他的数据类型布尔值(Boolean)-布尔值主要用来进行逻辑判断-布尔值只有两个true和false-使用typeof检查......
  • 面试题-java
    目录基础概念什么是java?什么是面向对象?java三大特性this,super关键字抽象类、接口抽象类abstract接口共同点区别抽象类能使用final修饰吗?==和equalsfinal关键字数据类型字......
  • Java两大工具库:Commons和Guava(6)
    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~   除了操作集合、限流和缓存,Guava还有另一个隐秘的功能:事件总线EventBus机制——是发布-订阅模式的实现,不需要显式......
  • 1.Java基础
    Java基础Java接口和抽象类有什么区别?共同点:都不能被实例化。都可以包含抽象方法。都可以有默认实现的方法(Java8可以用default关键字在接口中定义默认方法)。区别......
  • Java多线程并发06—CAS、AQS
    CAS(CompareAndSwap/Set)概念CAS函数,是比较并交换函数,它是原子操作函数。原理CAS是基于乐观锁的原理进行操作的。它总是认为自己可以成功完成操作。当多个线程同时使用CAS......
  • java——spring boot集成MongoDB——数据库安装和登录、简单使用
    参考文档,菜鸟教程:https://www.runoob.com/mongodb/mongodb-tutorial.html  参考文档、黑马教程:https://www.bilibili.com/video/BV1bJ411x7mq?p=1&vd_source=79bbd5b7......
  • Java异常
    Java异常异常指程序运行中出现的不期而至的各种状况。Java把异常当做对象来处理,并定义了一个基类java.lang.Throwable作为所有异常的超类。通常分为Error和Exception两......
  • JAVA 双亲委派与类加载器
    JAVA双亲委派与类加载器双亲委派虚拟机在加载类的过程中需要使用类加载器进行加载,而在Java中,类加载器有很多,那么当JVM想要加载一个.class文件的时候,到底应该由哪个类加......
  • Java流程控制
    Java流程控制用户交互Scannerjava.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户输入基本语法:Scanners=newScanner(System.in);通过Scann......
  • Java访问修饰符
    java中有两种类型的修饰符:访问修饰符和非修饰符。java中的访问修饰符指定数据成员,方法,构造函数或类的辅助功能(范围)。一共有4种类型的java访问修饰符:privatedefault......