面向对象设计模式:行为模式之责任链模式

news/2024/5/19 16:14:46 标签: 设计模式, 责任链模式, java

一、Backgroud 背景

在这里插入图片描述

  • 什么是推卸责任?
    • 坏的方面:去办事,被不同部门踢皮球
    • 好的方面:当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任。我们可以将多个对象组成一个职责链,然后按照它们在职责链上的顺序一个一个地找出谁来负责处理
  • 责任链模式:对于一个请求,能自己做就自己做,做不了就推卸给下一个人;下一个人能自己做就自己做,不能做再推卸给下一个人。
  • 优点:
    • Decouple the sender of a request from its receiver. 解耦请求的发送方及其接收方。
  • 缺点:
    • Latency. 延迟

二、责任链模式,Chain of Responsibility Pattern

When a client issues a request, the request propagates (传播) along the chain until a ConcreteHandler object takes responsibility for handling it.
当客户端发出请求时,请求沿链传播(传播),直到某个 ConcreteHandler 对象负责处理它。

2.1 Intent 意图

  • Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. 通过为多个对象提供处理(同一)请求的机会的方式避免将请求的发送方与其接收方耦合:客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,故而解耦。
  • Chain the receiving objects and pass the request along the chain until an object handles it. 链接接收对象并沿链传递请求直到某一个对象处理这个请求。

2.2 Applicability 适用情况

  • More than one object may handle a request, and the handler isn’t known a priori(多个对象可以处理一个请求,并且处理程序先验已知的). The handler should be ascertained automatically(处理程序应自动确定)
  • Want to issue a request to one of several objects without specifying the receiver explicitly(想要在不显式指定接收方的情况下向多个对象之一发出请求).
  • The set of objects that can handle a request should be specified dynamically(应动态指定可以处理请求的对象集).

2.3 类图

在这里插入图片描述

  • Handler
    • Defines an interface for handling requests.
    • (Optional) Implements the successor(后继者) link.
  • ConcreteHandler
    • Handles requests it is responsible for. q can access its successor. q If the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor.
  • Client
    • Initiates the request to a ConcreteHandler object on the chain.

2.4 责任链模式 Code

  • Support:问题支持抽象类
java">public abstract class Support {
    private String name;                    // 解决问题的实例的名字
    private Support next;                   // 要推卸给的对象
    public Support(String name) {           // 生成解决问题的实例
        this.name = name;
    }
    public Support setNext(Support next) {  // 设置要推卸给的对象
        this.next = next;
        return next;
    }
    public void support(Trouble trouble) {
        for (Support obj = this; true; obj = obj.next) {
            if (obj.resolve(trouble)) {
                obj.done(trouble);
                break;
            } else if (obj.next == null) {
                obj.fail(trouble);
                break;
            }
        }
    }
    public String toString() {              // 显示字符串
        return "[" + name + "]";
    }
    protected abstract boolean resolve(Trouble trouble); // 解决问题的方法
    protected void done(Trouble trouble) {  // 解决
        System.out.println(trouble + " is resolved by " + this + ".");
    }
    protected void fail(Trouble trouble) {  // 未解决
        System.out.println(trouble + " cannot be resolved.");
    }
}
  • NoSupport
java">public class NoSupport extends Support {
    public NoSupport(String name) {
        super(name);
    }
    protected boolean resolve(Trouble trouble) {     // 解决问题的方法
        return false; // 自己什么也不处理
    }
}
  • OddSupport
java">public class OddSupport extends Support {
    public OddSupport(String name) {                // 构造函数
        super(name);
    }
    protected boolean resolve(Trouble trouble) {    // 解决问题的方法
        if (trouble.getNumber() % 2 == 1) {
            return true;
        } else {
            return false;
        }
    }
}

  • SpecialSupport
java">public class SpecialSupport extends Support {
    private int number;                                 // 只能解决指定编号的问题
    public SpecialSupport(String name, int number) {    // 构造函数
        super(name);
        this.number = number;
    }
    protected boolean resolve(Trouble trouble) {        // 解决问题的方法
        if (trouble.getNumber() == number) {
            return true;
        } else {
            return false;
        }
    }
}

  • LimitSupport
java">public class LimitSupport extends Support {
    private int limit;                              // 可以解决编号小于limit的问题
    public LimitSupport(String name, int limit) {   // 构造函数
        super(name);
        this.limit = limit;
    }
    protected boolean resolve(Trouble trouble) {    // 解决问题的方法
        if (trouble.getNumber() < limit) {
            return true;
        } else {
            return false;
        }
    }
}


  • Trouble
java">public class Trouble {
    private int number;             // 问题编号
    public Trouble(int number) {    // 生成问题
        this.number = number;
    }
    public int getNumber() {        // 获取问题编号
        return number;
    }
    public String toString() {      // 代表问题的字符串
        return "[Trouble " + number + "]";
    }
}


  • Main
java">public class Main {
    public static void main(String[] args) {
        Support alice   = new NoSupport("Alice_NoSupport");
        Support bob     = new LimitSupport("Bob_LimitSupport", 100); //只能处理100以下的数
        Support charlie = new SpecialSupport("Charlie_SpecialSupport", 429); //只能处理429这一个数
        Support diana   = new LimitSupport("Diana_LimitSupport", 200); //只能处理200以下的数
        Support elmo    = new OddSupport("Elmo_OddSupport"); //只能处理奇数
        Support fred    = new LimitSupport("Fred_LimitSupport", 300); //只能处理三百以下的数
        // 形成职责链
        alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
        // 制造各种问题
        for (int i = 0; i < 500; i += 33) {
            alice.support(new Trouble(i));
        }
    }
}

2.4 责任链模式优缺点

  • 优点
    • 降低耦合度
    • 简化了对象,使得对象不需要知道链的结构
    • 增强给对象指派职责的灵活性:通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任
  • 缺点
    • 不能保证请求一定被接收
    • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用

http://www.niftyadmin.cn/n/123705.html

相关文章

23-03-05 自律

最近想学习后端java&#xff0c;发现有很多知识点需要记住。但是很多不容易记住&#xff0c;所以就查找了一下关于提交记忆力的方法。一个从物理出发&#xff1a;保证睡眠、适当运动、合理膳食、 经常转动眼睛、喝点可可饮料、早餐吃鸡蛋、吃葡萄干、多锻炼不常用的那只手&…

透过源码捋清Spring如何解决循环依赖

Spring如何解决循环依赖&#xff1f; 相信不少小伙伴在面试过程中被问到过这个问题&#xff0c;也有不少小伙伴看到这个问题会脱口而出&#xff1a;三级缓存&#xff01;但是&#xff0c;你真的了解spring解决循环依赖的过程吗&#xff1f;三级缓存是哪三级呢&#xff1f;他们…

k8s集群调度

1、调度约束Kubernetes 是通过 List-Watch 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。1.1 List-Watch 用户通过kubectl命令提交请求交给apiserver创建pod&#xff0c;然后apiserver将pod信息存放到etcd中&#xff0c;之后…

visio 新建个人模板

visio 新建个人模板 Generally, you can follow the steps below to apply the default font style, size, and color to a Visio template file. 通常&#xff0c;您可以按照以下步骤将默认字体样式、大小和颜色应用于Visio模板文件。 Click File > Options > Advanced…

Linux - CPU性能评估_详解查看CPU性能的命令

文章目录vmstat命令sar命令统计单个CPU的使用情况iostat -c 命令uptime命令小结vmstat命令 vmstat命令可以显示关于系统各种资源之间相关性能的简要信息&#xff0c;这里主要用它来看CPU的一个负载情况。 下面是vmstat命令在某个系统中的输出结果。 [rootVM-24-3-centos ~]# …

Android 基础知识4-3.6 ToggleButton(开关按钮)Switch(开关)详解

一、ToggleButton(开关按钮) 1.1、简介 ToggleButton 类似开关有开和关两种状态&#xff0c;不同的状态下可以有不同的文本。 public class ToggleButton extends CompoundButton Displays checked/unchecked states as a button with a "light" indicator …

浮点数的表示和运算

文章目录浮点数的表示表示溢出规格化IEEE754格式浮点数真值的计算公式范围浮点数的加减浮点数的乘除刷题小结浮点数的表示 表示 为什么会有浮点数&#xff1f;位数有限的情况下&#xff0c;既扩大了数的范围&#xff0c;也保持了数的精度。 浮点数的意思是小数点是浮动的&…

SQLI-Labs通关(2)5-7关

跟之前一样首先传参&#xff0c;然后查看注入点以及闭合 用and 11 and 12都没问题&#xff0c;接下来测试单引号 利用 and 12的时候会报错 利用order by来判断列数 得出一共三列 接下来就是联合查询 但是这个并不会回显 那么就利用盲注或者报错注入 在这里我们利用报错来测…