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;}@Overrideprotected void write(String message) {		System.out.println("标准控制台::Logger: " + message);}
}public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) {		System.out.println("错误控制台::Logger: " + message);}
}public class FileLogger extends AbstractLogger {public FileLogger(int level){this.level = level;}@Overrideprotected 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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蚂蚁集团5大开源项目获开放原子 “2023快速成长开源项目”

12月16日&#xff0c;在开放原子开源基金会主办的“2023开放原子开发者大会”上&#xff0c;蚂蚁集团主导开源的图数据库TuGraph、时序数据库CeresDB、隐私计算框架隐语SecretFlow、前端框架OpenSumi、数据域大模型开源框架DB-GPT入选“2023快速成长开源项目”。 &#xff08;图…

在Windows中如何安装XGBoost的C++版本进行模型训练和推理

1 前期软件及脚本准备 下载并安装 Git&#xff1a;从 Git 官方网站&#xff08;https://git-scm.com/downloads&#xff09;下载适用于 Windows 的 Git 安装程序&#xff0c;并按照安装程序的指示进行安装。 下载并安装 CMake&#xff1a;从 CMake 官方网站&#xff08;https:…

opencv入门到精通——图像上的算术运算

目录 目标 图像加法 图像融合 按位运算 目标 学习图像的几种算术运算&#xff0c;例如加法&#xff0c;减法&#xff0c;按位运算等。 您将学习以下功能&#xff1a;cv.add&#xff0c;cv.addWeighted等。 图像加法 您可以通过OpenCV函数cv.add()或仅通过numpy操作res …

第36节: Vue3 事件修饰符

在UniApp中使用Vue3框架时&#xff0c;你可以使用事件修饰符来更方便地处理用户交互事件。以下是一个示例&#xff0c;演示了如何在UniApp中使用Vue3框架使用事件修饰符&#xff1a; <template> <view> <button click.prevent"handleClick">Cli…

负载电容对晶振频率稳定性的影响

在电子系统中&#xff0c;晶振是产生精确频率的关键元件&#xff0c;而负载电容是影响晶振频率稳定性的重要因素之一。本文将深入探讨负载电容对晶振频率稳定性的影响&#xff0c;并分析如何通过合理的选择和设计来减小这种影响。 一、负载电容对晶振频率稳定性的影响 负载电…

End-to-End Object Detection with Transformers(DETR论文解析)

DETR:End-to-End Object Detection with Transformers 摘要引言3 DETR模型3.1 目标检测集合预测损失3.2 DETR体系结构摘要 我们提出了一种将目标检测视为直接集合预测问题的新方法。我们的方法简化了检测流程,有效地消除了许多手工设计的组件,如非极大值抑制程序或锚点生成,…

LangChain入门指南:定义、功能和工作原理

LangChain入门指南&#xff1a;定义、功能和工作原理 引言LangChain是什么&#xff1f;LangChain的核心功能LangChain的工作原理LangChain实际应用案例如何开始使用LangChain 引言 在人工智能的浪潮中&#xff0c;语言模型已成为推动技术革新的重要力量。从简单的文本生成到复…

IDEA版SSM入门到实战(Maven+MyBatis+Spring+SpringMVC) -SpringMVC @PathVariable 注解

IDEA版SSM入门到实战&#xff08;MavenMyBatisSpringSpringMVC) -SpringMVC PathVariable 注解 第一章 PathVariable 注解 1.1 PathVariable注解位置 Target(ElementType.PARAMETER)书写在参数前面 1.2 PathVariable注解作用 获取URL中占位符参数 占位符语法&#xff1a;{}…

oracle恢复分片和非分片备份?

分片备份命令参考&#xff1a;适合大数据库并行备份提高备份速度 对于超大数据库&#xff0c;混合有小文件和大文件表空间&#xff0c;section size 表示分片&#xff0c;大小一般大于32G&#xff0c;可结合通道数量设置最佳值。 run { allocate channel t1 type disk; alloc…

从安全性角度,看“可信数字底座”有何价值

文章目录 每日一句正能量前言概念对比安全技术对比思考与建议 每日一句正能量 不管现在有多么艰辛&#xff0c;我们也要做个生活的舞者。 前言 万向区块链此前提出“可信数字底座”这一概念和技术&#xff0c;即将区块链与物联网、人工智能、隐私计算等数字化技术相融合&#…

XPM_CDC_PULSE

MACRO_GROUP: XPM MACRO_SUBGROUP: XPM_CDC 1、Introduction 此宏将源时钟域中的脉冲同步到目标时钟域。源时钟域中任何大小的脉冲&#xff0c;如果正确启动&#xff0c;将生成单个目标时钟周期大小的脉冲。 为了正确操作&#xff0c;输入数据必须由目标时钟采样两次或…

Java八股文面试全套真题【含答案】- RabbitMQ篇

RabbitMQ 是什么&#xff1f;它解决了哪些问题&#xff1f; 答&#xff1a;RabbitMQ 是一个开源的消息代理中间件&#xff0c;用于在应用程序之间进行可靠的异步消息传递。它解决了应用程序间解耦、消息传递、负载均衡、故障恢复等问题。RabbitMQ 的核心概念是什么&#xff1f;…

LT8711UX,LT8711UXC ,LT8711UXD ,LT8711UXE1,LT8711UXE2的区别,选型的工程师注意了!!!

LT8711UX,LT8711UXC ,LT8711UXD ,LT8711UXE1,LT8711UXE2做为龙迅的重点物料&#xff0c;大家都不陌生。 可是它们不一样的后缀&#xff0c;又有什么不一样的应用区别呢&#xff1f; LT8711***均为DP/Type-C to HDMI系列的芯片。 LT8711UX&#xff0c;是一款带音频的Type-C…

2023美团机器人研究院学术年会成功举办

2023年12月19日&#xff0c;深圳市美团机器人研究院学术年会在清华大学深圳国际研究生院成功落下帷幕。会议回顾了研究院成立一年来的进展和成果&#xff0c;并邀请了各界专家共同讨论机器人技术的未来发展趋势。此外&#xff0c;年会期间还举办了首届低空经济智能飞行管理挑战…

可视化监控/安防视频云平台公共区域人员行为安全监控方案

大家在浏览新闻时&#xff0c;经常会看到某某地区有人员摔倒&#xff0c;长时间无人发现或人员闯入某危险区域管理人员未及时劝离&#xff0c;导致发生了意外事故的新闻。由于人力资源和人为巡检能力有限&#xff0c;在很多公共区域无法及时检测人员行为从而导致危险发生。为确…

模拟人员聚集报警

//模拟场景人员聚集 //范围5米 人员聚集数6个以及6个以上报警 设备信息类 package com.example.demo.udp;import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor;Builder AllArgsConstructor NoArgsConstructor Da…

Redis基础篇-004 Redis的Java客户端

Redis客户端分为三类&#xff1a; 命令行客户端图形化桌面客户端编程客户端&#xff08;java客户端&#xff09; redis可视化工具和客户端 1、 Jedis快速入门 Jedis的官网地址&#xff1a; https://github.com/redis/jedis 1.1 新建一个Maven工程并引入以下依赖 <!--引入…

【C语言进阶篇】你真的了解预处理吗? 预处理详细解析

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一、预定义符号的含义二、#define2.1 #define定义标识符2.2 在define定义标识符的注意事项 三、#define 定义宏&…

轻松搭建知识付费小程序:让知识传播更便捷

明理信息科技saas知识付费平台 在当今数字化时代&#xff0c;知识付费已经成为一种趋势&#xff0c;越来越多的人愿意为有价值的知识付费。然而&#xff0c;公共知识付费平台虽然内容丰富&#xff0c;但难以满足个人或企业个性化的需求和品牌打造。同时&#xff0c;开发和维护…

java SSM家庭财务管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM家庭财务管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…