7.设计模式之责任链模式

前言

责任链,即将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递, 链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象。为了避免请求发送者与多个请求处理者耦合在一起, 将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链; 当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程, 所以责任链将请求的发送者和请求的处理者解耦了。责任链是一种对象行为型模式

1. 责任链中的角色

1.1 抽象处理者

定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

1.2 具体处理者

实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

1.3 客户类

创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1.4 图示

在这里插入图片描述

2. 代码示例

2.1 定义抽象处理者

package com.wanlong.design_pattern.action.chainOfResponsibility;

/**
 * @author wanlong
 * @version 1.0
 * @description:
 * @date 2022/9/19 17:39
 */
public abstract class Leader {
    private Leader next;

    public Leader getNext() {
        return next;
    }

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

    //处理请求的方法
    public abstract void handleRequest(int LeaveDays);
}

2.2 定义具体处理者

2.2.1 定义具体处理者1

package com.wanlong.design_pattern.action.chainOfResponsibility;

/**
 * @author wanlong
 * @version 1.0
 * @description: 班主任责任链节点
 * @date 2022/9/19 17:40
 */

public class ClassAdviser extends Leader {
    @Override
    public void handleRequest(int LeaveDays) {
        if (LeaveDays <= 2) {
            System.out.println("班主任批准您请假" + LeaveDays + "天。");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(LeaveDays);
            } else {
                System.out.println("请假天数太多,没有人批准该假条!");
            }
        }
    }
}


2.2.2 定义具体处理者2

package com.wanlong.design_pattern.action.chainOfResponsibility;

/**
 * @author wanlong
 * @version 1.0
 * @description: 系主任责任链节点
 * @date 2022/9/19 17:41
 */


public class DepartmentHead extends Leader {
    @Override
    public void handleRequest(int LeaveDays) {
        if (LeaveDays <= 7) {
            System.out.println("系主任批准您请假" + LeaveDays + "天。");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(LeaveDays);
            } else {
                System.out.println("请假天数太多,没有人批准该假条!");
            }
        }
    }
}

2.2.3 定义具体处理者3

package com.wanlong.design_pattern.action.chainOfResponsibility;

/**
 * @author wanlong
 * @version 1.0
 * @description: 院长责任链节点
 * @date 2022/9/19 17:41
 */
public class Dean extends Leader {
    @Override
    public void handleRequest(int LeaveDays) {
        if (LeaveDays <= 10) {
            System.out.println("院长批准您请假" + LeaveDays + "天。");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(LeaveDays);
            } else {
                System.out.println("请假天数太多,没有人批准该假条!");
            }
        }
    }
}

2.3 定义客户类

package com.wanlong.design_pattern.action.chainOfResponsibility;

import org.junit.Test;

/**
 * @author wanlong
 * @version 1.0
 * @description: 责任链模式调用
 * @date 2022/9/19 17:39
 */
public class Client {

    @Test
    public void test() {

        //组装责任链
        Leader leader1 = new ClassAdviser();
        Leader leader2 = new DepartmentHead();
        Leader leader3 = new Dean();
        leader1.setNext(leader2);
        leader2.setNext(leader3);
        //提交请求
        leader1.handleRequest(8);
    }

}

运行结果:
院长批准您请假8天。

3. 总结

3.1 优缺点

3.1.1 优点

  1. 由于责任链的创建完全在客户端,使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
  2. 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
  3. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
  4. 责任分担。 每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则

3.1.2 缺点

  1. 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  2. 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响
  3. 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错, 如可能会造成循环调用。

3.2 使用场景

  1. 有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。
  2. 动态指定一组对象处理请求,或添加新的处理者。
  3. 在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

3.3 常见框架使用

  1. Java中,异常机制就是一种责任链模式。 一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch。
  2. Javascript语言中,事件的冒泡和捕获机制。
  3. Servlet开发中,过滤器的链式处理
  4. Struts2中,拦截器的调用也是典型的责任链模式
  5. 流程引擎activiti ,camunda通过流程控制业务流转
  6. shiro 过滤器链

3.4 注意事项

3.4.1 模式的扩展

职责链模式存在以下两种情况:

  1. 纯的职责链模式: 一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理。
  2. 不纯的职责链模式: 允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收。

以上,本人菜鸟一枚,如有问题,请不吝指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/19121.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

地狱级的字节跳动面试,6年测开的我被按在地上摩擦.....

前几天我朋友跟我吐苦水&#xff0c;这波面试又把他打击到了&#xff0c;做了快6年软件测试员。。。为了进大厂&#xff0c;也花了很多时间和精力在面试准备上&#xff0c;也刷了很多题。但题刷多了之后有点怀疑人生&#xff0c;不知道刷的这些题在之后的工作中能不能用到&…

SpringBoot+myBatis(plus)+MySQL+VUE最基础简易的前后端全栈demo制作

网站全栈制作&#xff1a; 一&#xff1a;后端 为了跟公司后端更好的扯皮&#xff08;不是&#xff09;&#xff0c;本人决定学一下java语言的后端接口书写。 项目制作&#xff1a;后端采用SpringBootmyBatis(plus)mysql&#xff08;IDE为IDEA软件&#xff09;。前端采用Vue…

macOS本地python环境/vscode/导入python包/设置python解释器

查看macbook本地是否有python环境 输入python或者python3&#xff0c;退出python环境使用exit()&#xff0c;别忘了括号 没有的话去官网安装https://www.python.org/ 2. 安装vscode 官网https://code.visualstudio.com/ 3. 安装插件 点击左边的“插件”按钮&#xff0c;安装…

wangzherongyao PMO

感谢【五一节】大家的相遇&#xff0c;总结下。 2023年05月02日&#xff0c;【第一组】组队开黑 我总结了下这天为什么打的那么好&#xff0c;首先赛季初段位在王者附近&#xff0c;大家心态重视程度也高&#xff0c;不轻敌&#xff0c;也不盲目&#xff0c;运营好兵线一步一步…

【需求响应】基于进化算法的住宅光伏电池系统需求响应研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Selenium原理以及Python从零实现

Selenium简介 Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。支持的浏览器包括IE&#xff08;7, 8, 9, 10, 11&#xff09;&#xff0c;Mozilla Firefox&#xff0c;Safari&#xff0c;Google Chrome&a…

OpenCV教程——处理图像像素及图像掩膜

1.像素值 像素值是图像被数字化时由计算机赋予的值&#xff0c;代表了图像中某一小方块&#xff08;即【像素点】&#xff09;的平均亮度信息。 灰度图像通常用8位表示一个像素&#xff0c;这样总共有256个灰度等级&#xff08;像素值在0&#xff5e;255之间&#xff09;。 …

【VSLAM】ORB-SLAM3安装部署与运行

心口如一&#xff0c;犹不失为光明磊落丈夫之行也。——梁启超 文章目录 :smirk:1. ORB-SLAM3介绍:blush:2. 代码安装部署1. 安装ros与opencv2. 安装Pangolin作为可视化和用户界面3. 安装Eigen3一个开源线性库&#xff0c;可进行矩阵运算4. 安装ORB-SLAM3 :satisfied:3. 案例运…

架构-软件工程模块-1

概述 这一模块选择题的分值比较多&#xff0c;案例题和论文也有能用上的地方。主要知识点会特殊标注或说明。 软件开发生命周期 软件工程三要素&#xff1a;方法、工具、过程。不会直接考&#xff0c;但可帮助记忆理解。 传统软件生命周期方法学分为&#xff1a;&#xff08;选…

ChatGPT的强化学习部分介绍——PPO算法实战LunarLander-v2

PPO算法 近线策略优化算法&#xff08;Proximal Policy Optimization Algorithms&#xff09; 即属于AC框架下的算法&#xff0c;在采样策略梯度算法训练方法的同时&#xff0c;重复利用历史采样的数据进行网络参数更新&#xff0c;提升了策略梯度方法的学习效率。 PPO重要的突…

尚硅谷-宋红康-JVM上中下篇完整笔记-JVM中篇

一.Class文件结构 1.概述 1.1 字节码文件的跨平台性 所有的JVM全部遵守Java虚拟机规范:Java SE Specifications&#xff0c;也就是说所有的JV环境都是一样的&#xff0c;这样一来字节码文件可以在各种JVM上运行。 1.2 Java的前端编译器 想要让一个Java程序正确地运行在JVM中&am…

177_模型_Power BI 进销存6大日期维度期初与期末

177_模型_Power BI 进销存6大日期维度期初与期末 一、背景 在经销存报表设计中&#xff0c;经常会遇到的便是期初与期末。当然我们这里说期初与期末指的是期初库存与期末库存。 这里的期一般常见的会有&#xff1a;年月日。本案例将演示 6 大日期维度&#xff0c;分别是&…

勒索病毒“顽疾”,没有“特效药”吗?

基础设施瘫痪、企业和高校重要文件被加密、毕业论文瞬间秒没……这就是六年前的今天&#xff0c;WannaCry勒索攻击爆发时的真实场景。攻击导致150多个国家数百万台计算机受影响&#xff0c;也让勒索病毒首次被全世界广泛关注。 六年后&#xff0c;勒索攻击仍是全球最严重的网络…

Kali E:Unable to locate package错误解决

默认的新装的kali 可能都会遇到这个安装报错E: Unable to locate package httrack问题&#xff0c;今天我记录下彻底解决过程和效果。 Command httrack not found, but can be installed with: apt install httrack Do you want to install it? (N/y)y apt install httrack Re…

什么是域名流量劫持?

作为传统的互联网攻击方式&#xff0c;域名流量劫持已经十分常见&#xff0c;这种网络攻击将会在不经授权的情况下控制或重定向一个域名的DNS记录。域名劫持的影响难以估量&#xff0c;因为它可以导致在访问一个网站时&#xff0c;用户被引导到另一个不相关的网站&#xff0c;对…

深入理解java虚拟机精华总结:运行时栈帧结构、方法调用、字节码解释执行引擎

深入理解java虚拟机精华总结&#xff1a;运行时栈帧结构、方法调用、字节码解释执行引擎 运行时栈帧结构局部变量表操作数栈动态连接方法返回地址 方法调用解析分派静态分派动态分派 基于栈的字节码解释执行引擎 运行时栈帧结构 Java虚拟机以方法作为最基本的执行单元&#xf…

Vue3 自定义指令让元素自适应高度,el-table在可视区域内滚起来

我始终坚持&#xff0c;前端开发不能满足于实现功能&#xff0c;而是需要提供优秀的交互与用户体验。即使没有产品没有UI的小项目&#xff0c;也可以自己控制出品质量&#xff0c;做到小而美。所以前端们不仅仅需要了解框架如何用&#xff0c;还要学习一些设计、交互、体验的知…

诗圣杜甫不同时期的代表作

杜甫一生大致分为四个时期。 中青年时期 青年时&#xff0c;作为官三代的杜甫并不缺钱&#xff0c;四处游历&#xff0c;与李白、高适唱和、仙游&#xff0c;成为佳话。这个时期杜甫的作品热血豪迈&#xff0c;气势蓬勃。代表作首推《望岳》&#xff1a; 岱宗夫如何&#xf…

2023/5/8总结

JAVA基础知识&#xff08;2&#xff09; 1.方法 1、方法定义 格式&#xff1a;public static void 方法名&#xff08;&#xff09;{ //方法体 } 2、方法调用 格式&#xff1a;方法名&#xff08;&#xff09;&#xff1b; 3、方法的通用格式 public static 返回值类型方法名&…

C++面向对象(黑马程序员)

内存分区模型 #include<iostream> using namespace std;//栈区数据注意事项&#xff1a;不要返回局部变量的地址 //栈区的数据由编译器管理开辟和释放int* func(int b) //形参数据也会放在栈区 {b 100;int a 10; //局部变量存放在栈区&#xff0c;栈区的数据在函数执…
最新文章