java设计模式学习之【责任链模式】
文章目录
- 引言
- 责任链模式简介
- 定义与用途
- 实现方式
- 使用场景
- 优势与劣势
- 在Spring框架中的应用
- 日志示例
- 代码地址
引言
在现实生活中,常常会遇到这样的场景:一个请求或命令需要经过多个层级的处理。例如,一个行政审批流程可能需要通过多个部门的审核。在软件开发中,我们可以使用责任链模式来模拟这种层级处理流程。责任链模式允许我们将请求的发送者和接收者解耦,将多个处理对象连成一条链,依次处理请求。
责任链模式简介
定义与用途
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理链传递,直到一个对象处理它为止。每个处理对象都包含逻辑来处理请求或将请求传递给链上的下一个对象。
实现方式
实现责任链模式通常包括以下几个关键组件:
- 处理器接口(Handler): 定义了处理请求的接口。
- 具体处理器(Concrete Handlers): 实现处理器接口,并执行具体的处理逻辑或将请求传递给链上的下一个处理器。
- 客户端(Client): 发起请求,并将请求传递给链上的第一个处理器。
使用场景
责任链模式适用于以下场景:
- 当多个对象可以处理一个请求,但具体由哪个对象处理在运行时才确定时。
- 当想在不明确指定接收者的情况下,向多个对象中的一个提交请求时。
- 当处理请求的一组对象应被动态指定时。
例如:
- 审批流程:不同级别的审批请求通过不同级别的管理层进行处理。
- 事件处理系统:例如 GUI 中的事件传递,事件可以由多个对象处理。
- 日志记录:根据消息的严重性级别,决定将其发送到不同的输出目标。
优势与劣势
- 优势
降低耦合度:请求的发送者和接收者之间没有直接的耦合关系。
增强灵活性:可以动态地改变链内的成员或调整其顺序。
易于扩展:可以通过增加新的处理器来扩展。 - 劣势
不能保证请求一定会被接收:所有处理者都可能不处理请求,使其未被处理。
对链中请求处理者的排列顺序和数量敏感。
在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
相关文章:
java设计模式学习之【责任链模式】
文章目录 引言责任链模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用日志示例代码地址 引言 在现实生活中,常常会遇到这样的场景:一个请求或命令需要经过多个层级的处理。例如,一个行政审批流程可能需要通过多个部门的审…...
docker 安装可视化工具 Protainer 以及 汉化
一、创建保存数据的卷 安装网址:Install Portainer BE with Docker on Linux - Portainer Documentation docker pull portainer/portainer二、根据portainer镜像创建容器 docker run -d -p 8000:8000 -p 9000:9000\ --name portainer --restartalways \ -v /var/r…...
【SpringBoot篇】详解Bean的管理(获取bean,bean的作用域,第三方bean)
文章目录 🍔Bean的获取🎄注入IOC容器对象⭐代码实现🛸根据bean的名称获取🛸根据bean的类型获取🛸根据bean的名称和类型获取 🎄Bean的作用域⭐代码实现🎈注意 🎄第三方Bean⭐代码实现…...
彭涛:2023年终复盘,工作,团队,个人!
眨眼2023即将结束,2024即将开启,每年这个时候,都会简单总结下自己这一年,既是对今年的一个复盘和回顾,也是对新一年的向往和期待。 我的2023年,大概分为 「个人」,「家庭」,「团队」…...
【数据结构和算法】---二叉树(2)--堆的实现和应用
目录 一、堆的概念及结构二、堆结构的实现2.1堆向下调整算法2.2堆向上调整算法2.3删除堆顶元素2.4插入元素2.5其他函数接口 三、堆结构的应用3.1堆排序3.2Top-k问题 四、堆概念及结构相关题目 一、堆的概念及结构 如果有一个数字集合,并把它的所有元素按完全二叉树…...
【大模型实践】基于文心一言的对话模型设计
文心一言(英文名:ERNIE Bot)是百度全新一代知识增强大语言模型,文心大模型家族的新成员,能够与人对话互动、回答问题、协助创作,高效便捷地帮助人们获取信息、知识和灵感。文心一言从数万亿数据和数千亿知识…...
聊聊PowerJob的StoreStrategy
序 本文主要研究一下PowerJob的StoreStrategy StoreStrategy tech/powerjob/worker/common/constants/StoreStrategy.java Getter AllArgsConstructor public enum StoreStrategy {DISK("磁盘"),MEMORY("内存");private final String des; }StoreStra…...
HTML+CSS+JS网页设计期末课程大作业 web课程设计 web前端开发 网页规划与设计
HTMLCSSJS网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计 💥 文章目录一、🚩 网站描述二、🎌 网站介绍三、🏴 网站类型A 个人博客主题B 人物明星主题C 旅游主题D 游戏主题E 动漫主题F 美食主题G 校园主题H 企…...
vscode | python | remote-SSH | Debug 配置 + CLIP4Clip实验记录
安装Extension 本地安装Remote-SSH、python 远程服务器上安装Python 难点:主机和远程服务器上安装Python扩展失败,可能是网络、代理等原因导致解决方法: 主机在官方网站下载Python扩展:https://marketplace.visualstudio.com/it…...
【Linux】实现windows主机与ubuntu虚拟机系统之间文件/字符复制粘贴
环境 硬件:通用PC 系统:Ubuntu 18.04 《 》Windows10 软件 :VMware Workstation 16 Pro 解决 0、现象 使用Ubuntu 虚拟机时,有时需要来回复制文件或者字符串到主机或虚拟机。 1、分析 2、思路 3、解决 //先安装open-vm-to…...
Ubuntu22.04-安装后Terminal无法调出
参考: Ubuntu20.04 终端打开不了的问题排查_ubuntu终端打不开-CSDN博客 https://blog.csdn.net/u010092716/article/details/130968032 Ubuntu修改locale从而修改语言环境_ubuntu locale-CSDN博客 https://blog.csdn.net/aa1209551258/article/details/81745394 问…...
ffmpeg两种windows版本区别说明
版本一 必须拷贝exe和dll文件才能使用,如果缺少dll则exe不正正常执行 如果缺少dll ,执行 exe会报错如下 版本2 直接拷贝exe就能使用,没有依赖的环境...
最新国内AI绘画Midjourney绘画提示词Prompt分享
一、Midjourney绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭…...
ChatGPT4.0(中文版)国内无限制免费版(附网址)
ChatGPT,由OpenAI开发的人工智能语言模型。它是你的数字对话伙伴,无论你有何问题或需要什么帮助,它都能提供有用的信息。 经过不断的研发和更新,ChatGPT的性能和功能得到了显著提升。现在,我们将重点介绍ChatGPT的两个…...
模拟电路基础知识笔记,你想知道的都有,建议收藏!
大家总说模电知识总是学不会,IC修真院为大家整理了模拟电子基础知识,看看你掌握了多少,文末可以获取全部哦。 文末可领全部文档 1、PN结是晶体二极管的基本结构,也是一般半导体器件的核心。 2、 射极输出器没有电压放大能力&am…...
【强化学习】基于蒙特卡洛MC与时序差分TD的简易21点游戏应用
1. 本文将强化学习方法(MC、Sarsa、Q learning)应用于“S21点的简单纸牌游戏”。 类似于Sutton和Barto的21点游戏示例,但请注意,纸牌游戏的规则是不同且非标准的。 2. 为方便描述,过程使用代码截图,文末附链…...
Pandas 高级教程——高级时间序列分析
Python Pandas 高级教程:高级时间序列分析 Pandas 提供了强大的时间序列处理功能,使得对时间序列数据进行高级分析变得更加灵活和方便。在本篇博客中,我们将深入介绍 Pandas 中的高级时间序列分析技术,并通过实例演示如何应用这些…...
解决Pycharm pip安装模块太慢问题,pycharm2022没有manage repositories配置镜像源
解决方案 方法清华阿里云中国科技大学华中理工大学 或者直接-i 加镜像 方法 URL写下面任意一个 清华 https://pypi.tuna.tsinghua.edu.cn/simple阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/华中理工大学 http:/…...
十二:爬虫-Scrapy框架(上)
一:Scrapy介绍 1.Scrapy是什么? Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架(异步爬虫框架) 通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片 Scrapy使用了Twisted异步网…...
BUUCTF Reverse/[2019红帽杯]Snake
BUUCTF Reverse/[2019红帽杯]Snake 下载解压缩后得到可执行文件,而且有一个unity的应用程序,应该是用unity编写的游戏 打开是一个贪吃蛇游戏 用.NET Reflector打开Assembly-CSharp.dll。(unity在打包后,会将所有的代码打进一个Ass…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
