责任链和策略设计模式-基于Java编程语言
作者:京东物流 钟磊
1 前言
最近在梳理接口逻辑的时候发现,代码中使用的策略和责任链设计模式给我留下了非常深刻的印象。一个业务逻辑流程通常非常适合使用责任链和策略设计模式来实现,因为一个业务需求通常可以拆分成一个个独立的逻辑处理单元并按顺序组合而成,而责任链设计模式可以很好的链接整个业务流程,同时策略设计模式可以将业务中变化的算法部分抽离出来,从而复用主要的公共逻辑并可以灵活替换业务算法,使用这两种设计模式可以灵活扩展我们的代码以适应不同的业务需求。由于这两种设计模式非常实用,下面简单介绍一下我对这两种设计模式的理解和它们在Spring框架源码中的应用。
2 责任链设计模式的一般定义
责任链设计模式是设计模式中的一种行为型设计模式。其基础结构类似于一个链条,整个链条由一个个单独的链环组成,每个链环在程序代码中就是一个独立的处理单元,每个处理单元都有自己负责的独特逻辑,当一个处理请求来到这个链条后,会依次沿着每个处理单元进行传递直到这个请求被处理完毕为止。
2.1 使用场景:
1.一个业务请求需要经过一组处理单元的处理。这种场景类似于一个业务逻辑流程中设置了多个功能不同的处理单元,一个业务请求需要经过这多个处理单元的串行处理。
2.程序中存在能处理同一个请求的多个处理单元,但决定具体使用哪个处理单元需要在程序运行时根据请求动态确定。
2.2 类图结构和Spring AOP框架中的应用
1:类图结构
2:责任链设计模式在Spring AOP框架中的应用
Spring框架中的AOP模块就使用了责任链设计模式将目标方法的一次调用过程包装成了一条方法调用链来增强目标方法。Spring AOP模块中包括了Before、After、AfterReturning、AfterThrowing、Around这五种通知方法,Spring AOP模块将这些通知方法和目标方法通过动态代理的方式包装成了一条调用链来分别履行各个通知模块的处理逻辑,下面是Spring AOP的源码分析图。
Spring AOP通过递归的方式来实现责任链的功能,首先将所有的通知方法进行排序,然后利用一个List索引来控制整个执行流程的开始和结束,在整个责任链中Before通知负责执行前置处理,After通知负责执行后置处理,AfterReturning方法负责在目标方法成功执行返回后执行处理逻辑,AfterThrowing方法负责在目标方法异常执行后执行处理逻辑。Spring AOP将通知方法包装成方法调用链上的每一个节点,巧妙地利用责任链模式完成了目标方法的处理增强。
3:泛化的责任链设计模式
在日常代码的编写中,责任链设计模式并不需要如此严格的结构,只要代码整体流程由一个个独立的处理单元构成,并且按一定顺序组合组合而成,那么也可以看作是一种更加泛化的责任链设计模式,也能很好的满足开闭原则,例如下面这种更加常用的代码结构。
上面这种结构同样也能实现责任链处理功能,也可以更加简洁的进行编写,同样可以很好的进修改和灵活扩展,在维护代码的适合也会更加清晰。
2.3 责任链模式的优点:
1.每个处理节点都有自己的独特的处理逻辑,明确各自在整个流程中的职责,符合类的单一职责原则。
2.构建的责任链可以根据业务需求进行灵活改变,能动态进行顺序调整以及动态插拔,满足重要的开闭原则。
3.降低了请求发送者以及请求处理者之间的耦合度。
3 策略设计模式的一般定义
策略设计模式同样也是设计模式中的一种行为型设计模式,其在结构上的表现就是将可变的算法策略部分从业务代码逻辑中独立出来,将这些算法策略形成策略池,从而可以随时替换和更新,使得我们的代码结构更加灵活、更易扩展。
3.1 使用场景
1:当代码需要根据上下文逻辑来选择使用不同的业务算法时,我们可以使用策略设计模式来优化代码的判断结构,从而避免大量的if/else分支判断。
2:当代码的主体处理逻辑大致相同,仅仅在部分的业务算法上存在不同时,可以将这些不同的业务算法抽离出来,从而能避免大量重复的代码编写,并能复用主体代码逻辑。
3.2 类图结构和Spring框架中的应用
1:类图结构
2:Spring框架中的应用
Spring框架中给我们开发者留下了非常多的扩展策略点,实现了可动态插拔的功能扩展,其中典型的一个策略扩展点就是BeanPostProcessor接口,BeanPostProcessor接口允许我们在Bean的初始化前和初始化后做一些逻辑处理策略来改变Bean的属性,允许我们对Bean进行改造和个性化,Spring AOP就是利用BeanPostProcessor这个策略扩展点实现了动态代理Bean的创建,下面是Spring AOP后置处理器的源码分析。
Spring AOP通过导入AspectJAwareAdvisorAutoProxyCreator这个实现了BeanPostProcessor接口的后置处理器,在Bean初始化后进行了一个动态代理类的创建,其在postProcessAfterInitaliztion方法中的WarpIfNecessary中方法中实现了代理类的创建。Spring框架利用这种模板加策略的设计模式让我们可以个性化扩展框架的功能,让框架变得非常灵活可扩展,我们也可以根据业务需求加入自己的BeanPostProcessor策略来实现自己的独特逻辑,很好地满足了重要的开闭设计原则。
3:泛化的策略设计模式
同样地我们也不必严格按照定义的策略设计模式进行编写,只要在整体上满足业务主体逻辑不变,将变化部分抽离出来,形成可以按需扩展的策略思想就行了,下面以SpringBoot自动装配的源码来说明这种更加泛化的策略模式。SpringBoot自动装配机制是按照用户当前的代码运行环境并结合@Conditional注解来动态为我们自动加载需要使用的类,这种策略设计模式是一种更加泛化的策略设计模式,同样满足策略设计模式的按需选择,动态插拔的设计原则。SpringBoot的自动装配机制的原理如下:
①SpringBoot在@EnableAutoConfiguration注解中使用了@import注解导入了
EnableAutoConfigurationImportSelector类。
②利用EnableAutoConfigurationImportSelector类的selectImports方法来加载jar包里面META-INF/spring.factories文件中配好的类。
③最后结合各种@Conditional注解来实现按需加载的策略设计模式。
SpringBoot这种按需自动装配的策略设计思想,在结构上并不严格符合策略设计模式的结构,但他的整体设计思想非常符合策略设计模式,我们在项目中也可以通过配置文件的方式来灵活切换我们代码中使用的策略算法。
3.3 策略设计模式的优点:
1:可以在程序运行时动态选择切换需要使用的独立业务算法。
2:将可变的业务算法与业务主体逻辑剥离,实现更加灵活的维护和扩展。
3:满足开闭原则,无需修改原有的代码逻辑就能实现不同业务算法灵活切换。
4 结合策略设计模式和责任链设计模式
将策略设计模式和责任链设计模式进行结合就能形成灵活可扩展的流程结构,能应对多变的业务需求,下面是将两者进行结合的结构图。
一个request在经过每一个handler处理单元时,会根据request的上下文内容选择合适的策略进行处理,然后将这所有的handler串联起来形成完整的业务流程。
5 总结
在日常代码的编写中,业务需求的变化总是不定的,这样会导致我们的代码会频繁的随着需求的改变进行调整,稍加不注意的话就会导致我们的代码非常臃肿和复杂,累加到一定程度后会变得难以维护,这时预先使用合适的代码设计模式能有效的缓解这种情况,文中描述的责任链和策略设计模式能有效满足代码编写的开闭原则,能更加有效的应对随时变化的业务需求。
责任链和策略设计模式-基于Java编程语言的更多相关文章
- 责任链模式-Chain of Responsibility(Java实现), 例2
责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...
- 责任链模式-Chain of Responsibility(Java实现), 例1
责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...
- 基于【 责任链模式】二 || 网关zuul过滤器封装
一.基于责任链模式封装网关拦截 上一篇文章中已经使用建造者模式对网关拦截进行封装,存在一个问题,在连接器build中,每一个拦截都要进行true判断,代码看起来冗余,下面使用责任链模式封装 1.基于责 ...
- 责任链模式Scala的7种实现
责任链模式是经典的GoF 23种设计模式之一,也许你已经了解这种模式.不管你是否熟悉,建议读者在阅读本文之前,不妨先思考下面三个问题: (1) 如何用多种风格迥异的编程范式来实现责任链模式? (2) ...
- 【责任链模式】责任链模式结合Spring实战Demo
备注: 责任链与策略模式有很多相似之处,如都是行为型设计模式,都能够处理代码中的if-else逻辑 主要区别在于: 策略模式 封装了算法,通过上下文对象去接受客户端的数据,根据数据类型执行不同的算法 ...
- Dubbo架构设计与源码解析(三)责任链模式
作者:周可强 一.责任链模式简介 1.责任链模式定义 责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对 ...
- 详解java设计模式之责任链模式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt175 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次 ...
- Java设计模式(14)责任链模式(Chain of Responsibility模式)
Chain of Responsibility定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合, ...
- java设计模式解析(11) Chain责任链模式
设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析(4) ...
- 重学 Java 设计模式:实战责任链模式「模拟618电商大促期间,项目上线流程多级负责人审批场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 场地和场景的重要性 射击
随机推荐
- 什么是VXLAN?为什么需要VXLAN?
摘要:本文介绍了什么是VXLAN,以及VXLAN的基本概念和工作原理,包括:为什么需要VXLAN?VXLAN与VLAN之间有啥不同?什么是VTEP?什么是VNI?VXLAN报文是如何封装的?VXLAN ...
- vue2升级vue3:vue3 hooks库选用
之前a-hooks:https://ahooks.js.org/,比react-use 精简好用.但是没有vue版本的. 网上有个人实现的:https://github.com/dewfall123/ ...
- 专注提升用户体验,Superset 1.3发布!
近期Superset发布了新的版本1.3.0,此版本专注于提升用户体验.并进行了大量的改进与错误修复. 用户体验 此版本的一个主要目标是改进仪表盘原生过滤器.这些过滤器的级别为仪表盘级别,而不是图表级 ...
- 2023 年如何将您的应用提交到 App Store
您夜以继日地工作来创建您的梦想应用程序.最后,是时候向全世界宣布您的应用程序了.但不知道如何将您的应用提交到 App Store? 为您的商店获取现成的移动应用程序 将应用程序提交到 App Stor ...
- 朋友们,就在今天,JDK 21,它终于带着重磅新特性正式发布了!
你好呀,我是歪歪. 朋友们,好消息,好消息,重磅好消息. 从今年年初就一直在喊的具有革命性.未来性.开创新纪元的 JDK 21 按照官方的时间计划表,今天终于是要正式 GA 了: https://op ...
- PPT 常见的页面框架
分割 分列 居中 包围 对称 杂志 https://www.bilibili.com/video/BV1ha411g7f5?p=19
- Spring Boot 2.x基础教程:使用LDAP来管理用户与组织数据
很多时候,我们在做公司系统或产品时,都需要自己创建用户管理体系,这对于开发人员来说并不是什么难事,但是当我们需要维护多个不同系统并且相同用户跨系统使用的情况下,如果每个系统维护自己的用户信息,那么此时 ...
- 在Windows下配置Clang编译器
Preferences Linux & macOS 平台LLVM 相关工具链下载 2019年,在Windows下配置Clang编译器 Visual Studio 2022 中使用 Clang ...
- Spark SQL 字段血缘在 vivo 互联网的实践
作者:vivo互联网服务器团队-Hao Guangshi 一.背景 字段血缘是在表处理的过程中将字段的处理过程保留下来.为什么会需要字段血缘呢? 有了字段间的血缘关系,便可以知道数据的来源去处,以及字 ...
- vue-router路由复用后页面没有刷新
vue-router提供了页面路由功能,可以用来构建单页面应用,在使用vue-router的动态路由匹配的时候,遇到了url变化了,但是页面却没有任何动静的问题,记录一下. 动态路由匹配url变化了, ...