java设计模式学习之【责任链模式】

文章目录

  • 引言
  • 责任链模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 在Spring框架中的应用
  • 日志示例
  • 代码地址

引言

在现实生活中,常常会遇到这样的场景:一个请求或命令需要经过多个层级的处理。例如,一个行政审批流程可能需要通过多个部门的审核。在软件开发中,我们可以使用责任链模式来模拟这种层级处理流程。责任链模式允许我们将请求的发送者和接收者解耦,将多个处理对象连成一条链,依次处理请求。

责任链模式简介

定义与用途

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理链传递,直到一个对象处理它为止。每个处理对象都包含逻辑来处理请求或将请求传递给链上的下一个对象。

实现方式

实现责任链模式通常包括以下几个关键组件:

  • 处理器接口(Handler): 定义了处理请求的接口。
  • 具体处理器(Concrete Handlers): 实现处理器接口,并执行具体的处理逻辑或将请求传递给链上的下一个处理器。
  • 客户端(Client): 发起请求,并将请求传递给链上的第一个处理器。

使用场景

责任链模式适用于以下场景:

  • 当多个对象可以处理一个请求,但具体由哪个对象处理在运行时才确定时。
  • 当想在不明确指定接收者的情况下,向多个对象中的一个提交请求时。
  • 当处理请求的一组对象应被动态指定时。

例如:

  1. 审批流程:不同级别的审批请求通过不同级别的管理层进行处理。
  2. 事件处理系统:例如 GUI 中的事件传递,事件可以由多个对象处理。
  3. 日志记录:根据消息的严重性级别,决定将其发送到不同的输出目标。

优势与劣势

  • 优势
    降低耦合度:请求的发送者和接收者之间没有直接的耦合关系。
    增强灵活性:可以动态地改变链内的成员或调整其顺序。
    易于扩展:可以通过增加新的处理器来扩展。
  • 劣势
    不能保证请求一定会被接收:所有处理者都可能不处理请求,使其未被处理。
    对链中请求处理者的排列顺序和数量敏感。

在Spring框架中的应用

在Spring框架中,责任链模式通常用于处理一系列的处理步骤或中间件。这种模式在Spring的多个组件中得到应用,最典型的是在Spring Security和Spring MVC中。

1. Spring Security中的责任链应用

在Spring Security中,责任链模式体现在过滤器链(Filter Chain)中。
每个请求都会通过一系列的安全过滤器,每个过滤器执行不同的安全检查和任务。这些过滤器包括:

Authentication Filter:负责用户认证。
Authorization Filter:负责检查用户是否有权限访问特定资源。
Exception Translation Filter:负责处理在安全认证过程中抛出的异常。
每个过滤器处理请求后决定是否将请求传递给链中的下一个过滤器,或者是终止请求并返回响应。这正是责任链模式的核心特征。

2. Spring MVC中的责任链应用

在Spring MVC中,拦截器(Interceptors)也是一种责任链模式的体现。
拦截器用于在处理请求前后执行各种任务,比如日志记录、权限检查、事务处理等。你可以定义多个拦截器,并将它们链接在一起,形成一个拦截器链。
每个拦截器决定是否:

在Controller处理请求之前执行某些操作。
在Controller处理完请求后执行某些操作。

3. Spring中的Filter Chain

Spring的另一个责任链应用是Spring Web中的Filter Chain。在Spring Web中,你可以定义多个过滤器来处理Web请求。
每个过滤器执行完任务后,可以决定是否将请求传递给链中的下一个过滤器。
这些过滤器可以处理跨站请求伪造(CSRF)保护、CORS、编码问题等。

日志示例

在这里插入图片描述
步骤 1:创建抽象日志类
首先定义了一个 AbstractLogger 抽象类,作为日志处理者的基类。

public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;

   protected int level;

   // 链中的下一个责任元素
   protected AbstractLogger nextLogger;

   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }

   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }

   abstract protected void write(String message);
	
}

这个类定义了日志级别和处理请求的方法。如果此处理者能处理该级别的日志,它将输出日志;否则,它将请求转发给链中的下一个处理者。

步骤 2:创建具体的日志处理类
创建了具体的日志处理者类,扩展了 AbstractLogger。

public class ConsoleLogger extends AbstractLogger {

   public ConsoleLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("标准控制台::Logger: " + message);
   }
}

public class ErrorLogger extends AbstractLogger {

   public ErrorLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("错误控制台::Logger: " + message);
   }
}

public class FileLogger extends AbstractLogger {

   public FileLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("文件::Logger: " + message);
   }
}

每个具体的处理者类负责处理特定级别的日志消息。

步骤 3:创建不同类型的日志处理者并形成链
定义了一个客户端类 ChainPatternDemo 来创建日志处理者链并使用该链处理消息。

public class ChainPatternDemo {
	
   private static AbstractLogger getChainOfLoggers(){

      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

      // 形成责任链
      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);

      return errorLogger;	
   }

   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();

      loggerChain.logMessage(AbstractLogger.INFO, 
         "这是一条信息级别的消息。");

      loggerChain.logMessage(AbstractLogger.DEBUG, 
         "这是一条调试级别的消息。");

      loggerChain.logMessage(AbstractLogger.ERROR, 
         "这是一条错误级别的消息。");
   }
}

在这里插入图片描述

在这个客户端中,我们创建了不同级别的日志处理者并连接它们形成一条链。然后,我们发送不同级别的消息给责任链,可以看到消息被相应级别的处理者处理。

这个示例演示了责任链模式在处理具有不同处理级别的请求中的效力。通过改变链的结构或成员,可以灵活地改变请求处理的方式。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

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

相关文章

【视觉实践】使用Mediapipe进行目标检测:杯子检测和椅子检测实践

目录 1 Mediapipe 2 Solutions 3 安装mediapipe 4 实践 1 Mediapipe Mediapipe是google的一个开源项目,可以提供开源的、跨平台的常用机器学习(machine learning,ML)方案。MediaPipe是一个用于构建机器学习管道</

成为一名FPGA工程师:面试题与经验分享

在现代科技领域&#xff0c;随着数字电子技术的迅猛发展&#xff0c;FPGA&#xff08;可编程逻辑器件&#xff09;工程师成为了备受瞩目的职业之一。FPGA工程师不仅需要掌握硬件设计的基本原理&#xff0c;还需要具备良好的编程能力和解决问题的实践经验。面对如此竞争激烈的行…

DRF从入门到精通二(Request源码分析、DRF之序列化、反序列化、反序列化校验、序列化器常用字段及参数、source、定制字段、保存数据)

文章目录 一、Request对象源码分析区分原生request和新生request新的request还能像原来的reqeust一样使用吗源码片段分析总结&#xff1a; 二、DRF之序列化组件序列化介绍序列化步骤序列化组件的基本使用反序列化基本使用反序列化的新增反序列化的新增删除单条 反序列化的校验序…

老师的责任和义务

作为一名老师&#xff0c;我们的责任和义务是重大的。在教育领域&#xff0c;我们扮演着至关重要的角色&#xff0c;肩负着培养下一代人才的重任。下面&#xff0c;我将以知乎的口吻&#xff0c;从几个方面谈谈老师的责任和义务。 确保学生获得高质量的教育。这包括制定合理的教…

【XR806开发板试用】通过http请求从心知天气网获取天气预报信息

1. 开发环境搭建 本次评测开发环境搭建在windows11的WSL2的Ubuntu20.04中&#xff0c;关于windows安装WSL2可以参考文章: Windows下安装Linux(Ubuntu20.04)子系统&#xff08;WSL&#xff09; (1) 在WSL的Ubuntu20.04下安装必要的工具的. 安装git: sudo apt-get install git …

在线客服系统推荐:优质选择助您提升客户服务体验

大部分企业依靠在线客服系统和客户达成联系&#xff0c;他为客户和企业之间建立了有效的沟通桥梁。市场上这么多的在线客服系统哪个好呢&#xff1f; 1、明确自己的需求。 这一点是最重要的&#xff0c;要先明确公司使用客服系统是想做售前咨询还是售后服务。不同的需求相对应…

[笔记]ByteBuffer垃圾回收

参考&#xff1a;https://blog.csdn.net/lom9357bye/article/details/133702169 public static void main(String[] args) throws Throwable {List<Object> list new ArrayList<>();Thread thread new Thread(() -> {ByteBuffer byteBuffer ByteBuffer.alloc…

自动评估作业,支持订正最终得分、查看关联代码|ModelWhale 版本更新

冬至时节&#xff0c;2023 已进入尾声&#xff0c;ModelWhale 于今日迎来新一轮的版本更新&#xff0c;与大家一起静候新年的到来。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; 自动评估作业 新增 提交代码&#xff08;团队版✓ &#xff09;新增…

【Netty】编解码器

目录 Java的编解码Netty编解码器概念解码器(Decoder)编码器(Encoder)编码解码器Codec Java的编解码 编码&#xff08;Encode&#xff09;称为序列化&#xff0c; 它将对象序列化为字节数组&#xff0c;用于网络传输、数据持久化或者其它用途。 解码&#xff08;Decode&#x…

本地无法连接注册中心eureka,如何进行feign调用,并快速启动本地调试?

前言 今年进入了个新公司&#xff0c;接手代码时遇到了比较蛋疼的事情&#xff0c;本地代码调试遇到了层层阻碍&#xff0c;无法一键简单启动就算了&#xff0c;我就忍了&#xff0c;一番操作终于启动起了了&#xff0c;启动又慢&#xff0c;启动了2~3分钟&#xff0c;后面调本…

【音视频】remb twcc原理

目录 twcc简介 WebRTC REMB 参考文档 twcc简介 TWCC全称是Transport wide Congestion Control&#xff0c;是webrtc的最新的拥塞控制算法。其原理是在接收端保存数据包状态&#xff0c;然后构造RTCP包反馈给发送端&#xff0c;反馈信息包括包到达时间、丢包状态等&#xff…

养老院自助饮水机(字符设备驱动)

目录 1、项目背景 2、驱动程序 2.1 三层架构 2.2 驱动三要素 2.3 字符设备驱动 2.3.1 驱动模块 2.3.2 应用层 3、设计实现 3.1 项目设计 3.2 项目实现 3.2.1 驱动模块代码 3.2.2 用户层代码 4、功能特性 5、技术分析 6. 总结与未来展望 1、项目背景 养老院的老人…

社交网络分析(汇总)

这里写自定义目录标题 写在最前面社交网络分析系列文章汇总目录 提纲问题一、社交网络相关定义和概念提纲问题1. 社交网络、社交网络分析&#xff1b;2. 六度分隔理论、贝肯数、顿巴数&#xff1b;3. 网络中的数学方法&#xff1a;马尔科夫过程和马尔科夫链、平均场理论、自组织…

仿悬赏猫任务平台源码 悬赏任务系统源码 带支付接口

源码介绍 最新仿悬赏猫任务平台源码 悬赏任务系统源码 带支付接口&#xff0c; 全新开发悬赏任务系统&#xff0c;功能齐全&#xff0c;包含接任务&#xff0c;发布任务&#xff0c; 店铺关注&#xff0c;置顶推荐&#xff0c;排行榜&#xff0c;红包大厅&#xff0c;红包抽奖…

Android Studio如何实现 成语接龙游戏(简单易上手)

该项目是一个基于Android Studio和Java语言编写的成语接龙游戏App。成语接龙是一种经典的中文文字游戏&#xff0c;旨在测试玩家的词汇量和思维敏捷性。该成语接龙游戏App旨在提供一种有趣、挑战性和教育性的游戏体验。玩家可以通过游戏提高自己的中文词汇量和思维敏捷性&#…

Text Intelligence - TextIn.com AI时代下的智能文档识别、处理、转换

本指南将介绍Text Intelligence&#xff0c;AI时代下的智能文档技术平台 Textin.com 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认…

KubeSphere应用【六】中间件部署

一、Mysql部署 1.1创建配置字典 [client] default-character-setutf8mb4 [mysql] default-character-setutf8mb4[mysqld] sql_modeSTRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION init_connectSET…

【分治算法】之汉诺塔问题

汉诺塔问题 三根柱子 把A柱子上的盘子全部挪到C上&#xff0c;且每次挪动的时候 小的必须在大的上面 分治算法的思想; 分&#xff1a;把一个大问题拆成若干个小的子问题&#xff0c;每个子问题相互独立&#xff1b; 治&#xff1a;求解每个子问题的&#xff08;递归&#xf…

前端FLV视频直播解决方案

项目背景&#xff1a; 1. 后台给出一个地址&#xff0c;持续不断的推送flv视频流。 2.前端需要接收视频流&#xff0c;并寻找合适的播放插件。 一开始&#xff1a; 其实用的是xgplayer&#xff08;西瓜视频&#xff09;。 官网地址&#xff1a;西瓜播放器 使用的是直播&a…

开放式耳机怎么选?2023高人气品牌推荐:新手避坑必看!

自从开放式耳机风靡市场以来&#xff0c;大家对于开放式耳机的选购也越发摸不着头脑。价格从百元到千元不等&#xff0c;就连大品牌的产品口碑也褒贬不一。 不少人私信向我询问&#xff1a; 1、难道只有千元价位的开放式耳机才好吗&#xff1f;2、是否有价格更实惠且性价比更…