首页 > 编程语言 >责任链和策略设计模式-基于Java编程语言

责任链和策略设计模式-基于Java编程语言

时间:2023-02-20 09:23:42浏览次数:39  
标签:逻辑 Java 策略 编程语言 Spring 代码 AOP 设计模式

作者:京东物流 钟磊

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,策略,编程语言,Spring,代码,AOP,设计模式
From: https://www.cnblogs.com/Jcloud/p/17136208.html

相关文章

  • 看完这篇原型设计模式,还不会,请你吃瓜
    概述使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。在软件系统开发中,有时候会遇到这样的情况:我们需要用到多个相同实例,最简单直接的方法是通过多次......
  • java的Stream
    代码List<Student>all=Student.getAll();//转换成数组过滤所有的男性Student[]students=all.stream().filter(s->"男".equalsIgnoreCase(s.getSex()))......
  • 读Java实战(第二版)笔记15_并行数据处理与性能
    1. Stream1.1. 允许你声明性地将顺序流转变成并行流1.2. 能对这些集合执行操作流水线,可以充分利用计算机的多个核2. 并行流2.1. 把内容拆分成多个数据块,用不同线......
  • Odoo 通过Javascript调用模型中自定义方法
    实践环境Odoo14.0-20221212(CommunityEdition)代码实现在js脚本函数中调用模型中自定义方法:this._rpc({model:'demo.wizard',//模型名称,即模型类定义中_na......
  • 《深入理解java虚拟机》第七章读书笔记——虚拟机类加载机制
    系列文章目录和关于我一丶虚拟机类加载机制是什么java虚拟机将描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可用被虚拟机直接使用的jav......
  • JavaScript回调函数
    回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。在JavaScript中函数也是对象的一种,同样对象可以作为参数传......
  • Java String为什么不可变?
    publicfinalclassStringimplementsjava.io.Serializable,Comparable<String>,CharSequence{privatefinalcharvalue[]; //...}String类中使用final......
  • Java 如何通过JDBC 操作数据库
    JDBC是Java数据库连接,即JavaDataBaseConnectivity。JDBC可让Java通过程序操作关系型数据库,可基于驱动程序实现与数据库的连接与操作。JDBC有统一的API,提供一致的......
  • Java实现对MongoDB的AND、OR和IN操作
    很全的JAVA操作mongodb:​​http://www.blogjava.net/xiaomage234/archive/2012/08/06/384904.html​​ 转的: AND:publicvoidtestAnd(){//agender='female'ANDag......
  • 常用java路径
    System.out.println(LmsFEMain.class.getClassLoader().getResource(""));//file:/E:/workspace/FEServer/bin/System.out.println(ClassLoader.getSystemResource("")......