作者:京东物流 钟磊

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编程语言的更多相关文章

  1. 责任链模式-Chain of Responsibility(Java实现), 例2

    责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...

  2. 责任链模式-Chain of Responsibility(Java实现), 例1

    责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...

  3. 基于【 责任链模式】二 || 网关zuul过滤器封装

    一.基于责任链模式封装网关拦截 上一篇文章中已经使用建造者模式对网关拦截进行封装,存在一个问题,在连接器build中,每一个拦截都要进行true判断,代码看起来冗余,下面使用责任链模式封装 1.基于责 ...

  4. 责任链模式Scala的7种实现

    责任链模式是经典的GoF 23种设计模式之一,也许你已经了解这种模式.不管你是否熟悉,建议读者在阅读本文之前,不妨先思考下面三个问题: (1) 如何用多种风格迥异的编程范式来实现责任链模式? (2) ...

  5. 【责任链模式】责任链模式结合Spring实战Demo

    备注: 责任链与策略模式有很多相似之处,如都是行为型设计模式,都能够处理代码中的if-else逻辑 主要区别在于: 策略模式 封装了算法,通过上下文对象去接受客户端的数据,根据数据类型执行不同的算法 ...

  6. Dubbo架构设计与源码解析(三)责任链模式

    作者:周可强 一.责任链模式简介 1.责任链模式定义 责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对 ...

  7. 详解java设计模式之责任链模式

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt175 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次 ...

  8. Java设计模式(14)责任链模式(Chain of Responsibility模式)

    Chain of Responsibility定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合, ...

  9. java设计模式解析(11) Chain责任链模式

    设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析(4) ...

  10. 重学 Java 设计模式:实战责任链模式「模拟618电商大促期间,项目上线流程多级负责人审批场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 场地和场景的重要性 射击

随机推荐

  1. 云小课 | 守护网络安全不是问题,iptables的四表五链为你开启“八卦阵”

    摘要:担心网络基本安全?iptables八卦阵为您守护!本文带您一起了解iptables的相关知识. 网络世界就和现实世界一样,总是会有些不怀好意的"人"出现,扫扫你的端口啊,探测 ...

  2. 教你搭建一个Telegraf+Influxdb+Grafana 监控系统

    摘要:本文利用华为HECS云服务器进行监控系统部署. 本文分享自华为云社区<使用华为HECS云服务器打造Telegraf+Influxdb+Grafana 监控系统[华为云至简致远]>,作 ...

  3. 跟我读论文丨ACL2021 NER BERT化隐马尔可夫模型用于多源弱监督命名实体识别

    摘要:本文是对ACL2021 NER BERT化隐马尔可夫模型用于多源弱监督命名实体识别这一论文工作进行初步解读. 本文分享自华为云社区<ACL2021 NER | BERT化隐马尔可夫模型用于 ...

  4. 【“互联网+”大赛华为云赛道】IoT命题攻略:仅需四步,轻松实现场景智能化设计

    摘要:仅需四步,轻松实现场景智能化设计,作品开发超轻松. 本文分享自华为云社区<["互联网+"大赛华为云赛道]IoT命题攻略:仅需四步,轻松实现场景智能化设计>,作者: ...

  5. Koa、koa-router、koa-jwt 鉴权详解:分模块鉴权实践总结

    首先看koa-router koa-router use 熟悉Koa的同学都知道use是用来注册中间件的方法,相比较Koa中的全局中间件,koa-router的中间件则是路由级别的. koa-rout ...

  6. 再谈BOM和DOM(4):DOM0/DOM2事件处理分析

    JavaScript能够让网站对用户的各种操作及时做出"反馈",响应用户交互行为,而这些就是:DOM,事件以及事件处理 DOM就是操作的元素,这个看<再谈BOM和DOM(1) ...

  7. MyBatis ORA-01465: 无效的十六进制数字

    MyBatis 在插入 Oralce 时报:ORA-01465: 无效的十六进制数字 解决方法: # 插入或更新时 String -> BLOB字段:RAWTOHEX(#{字段名}) Strin ...

  8. esp8266 水墨屏显示中文之简单字库

    esp8266 驱动水墨屏显示中文,假设在此之前已经安装好arduino,配置好esp8266的开发环境.水墨屏显示中文的步骤如下: 一.下载库 安装esp8266需要的库文件: GxEPD2 屏幕驱 ...

  9. 【JAVA基础】MySQL配置

    mySQL配置 数据库连接 初始化配置 --创建用户 并授权 create user 'injasup'@'%' identified by 'supplier@2023#!'; GRANT SELE ...

  10. Python 3.12 抢先看——关于 f-string 的改动

    Python 3.12 抢先看--关于 f-string 的改动 哈喽大家好,我是咸鱼 相信小伙伴们对 python 中的 f-string 都不陌生 f-string 是格式化字符串的缩写,是以小写 ...