工作中责任链模式用法及其使用场景?

简介: 工作中责任链模式用法及其使用场景?

前言

笔者是金融保险行业,有这么一种场景,业务员录完单后提交核保,这时候系统会对保单数据进行校验,如不允许手续费超限校验,客户真实性校验、费率限额校验等等,当校验一多时,维护起来特别麻烦,代码耦合度太高。


这里使用责任链模式,将每个校验模块之间互相独立,在后面新增校验时,只需要往容器中插入即可,且可以给每个模块赋予优选级进行排序,利于管理。与Spring框架结合,利于类的管理。

正文

处理器模板

public interface CheckProcessor {
    /**
     * 逻辑处理
     * @param policyInfo
     * @param exposeProcessor
     */
    public void invoke(PolicyInfo policyInfo,ExposeProcessor exposeProcessor) throws Exception;
}

处理器实现类

手续费校验器

public class CommissionRateCheckProcessor implements CheckProcessor {
    @Override
    public void invoke(PolicyInfo policyInfo, ExposeProcessor exposeProcessor) throws Exception {
        System.out.println("完成手续费校验");
        //调用下个处理器
        exposeProcessor.invoke(policyInfo);
    }
}

客户真实性校验器

public class CustomerCheckProcessor implements CheckProcessor {
    @Override
    public void invoke(PolicyInfo policyInfo, ExposeProcessor exposeProcessor) throws Exception {
        System.out.println("完成客户真实性校验");
        //调用下个处理器
        exposeProcessor.invoke(policyInfo);
    }
}

保险费率校验器

public class PremiumRateCheckProcessor implements CheckProcessor {
    @Override
    public void invoke(PolicyInfo policyInfo, ExposeProcessor exposeProcessor) throws Exception {
        System.out.println("完成保险费率校验");
        //调用下个处理器
        exposeProcessor.invoke(policyInfo);
    }
}

入口管理类

public class ExposeProcessor {
    private  int index;
    private  static List<CheckProcessor> processor=new ArrayList();
    static {
        setProcessor(new CustomerCheckProcessor());
        setProcessor(new CommissionRateCheckProcessor());
        setProcessor(new PremiumRateCheckProcessor());
    }
    /**
     * 处理器
     */
    public  void invoke(PolicyInfo policyInfo) throws Exception {
      //获取容器中所有的处理器
        List processors = getProcessors();
        if (processors.size()==0||index==processors.size()){
            return;
        }
        //根据指针指向,调用处理器。并把指针指向下一个
        CheckProcessor processor = (CheckProcessor)processors.get(index++);
        //调用处理器
        processor.invoke(policyInfo,this);
    }
    /**
     * 处理器集
     */
    private  List getProcessors(){
        return processor;
    }
    public static void setProcessor(CheckProcessor checkProcessor){
        processor.add(checkProcessor);
    }
}
  1. 获取容器中的校验器
  2. 校验是否往下执行,如果处理器数量为空,或者当前指针已经指向尾部时,则不再往下执行
  3. 将管理器以及请求参数传递到处理器中进行处理
  4. 处理器执行完毕后,调用管理器的invoke方法来启动责任链中的下个处理器

测试用例

    public static void main(String[] args) {
        ExposeProcessor exposeProcessor=new ExposeProcessor();
        try {
            exposeProcessor.invoke(new PolicyInfo());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

e17ef6ce9d14b8265a62e38c607a873f_bc8f64e4e8584d2c962e7c509ebdf861.png

以前代码有很多可以改进的地方,如与IOC框架结合,将每个处理器交给IOC容器进行管理,在获取处理器方法中可以直接从IOC容器中获取CheckProcessor 类型的所有实现类。

结合Spring IOC

@Service
public class ExposeProcessor implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    private  int index;
    private  List<CheckProcessor> processor=new ArrayList();
    /**
     * 处理器
     */
    public  void invoke(PolicyInfo policyInfo) throws Exception {
        List processors = getProcessors();
        if (processors.size()==0||index==processors.size()){
            return;
        }
        CheckProcessor processor = (CheckProcessor)processors.get(index++);
        processor.invoke(policyInfo,this);
    }
    /**
     * 处理器集
     */
    private  List getProcessors(){
        Map<String, CheckProcessor> beansOfType = this.applicationContext.getBeansOfType(CheckProcessor.class);
        return beansOfType.values().stream().collect(Collectors.toList());
    }
    public void setProcessor(CheckProcessor checkProcessor){
        processor.add(checkProcessor);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
}

管理类实现ApplicationContextAware接口,并重写其setApplicationContext方法,将IOC上下文对象保存下来。

从IOC容器中获取类型为CheckProcessor 的类

将管理类加上@Service注解交由IOC容器进行管理

在所有的校验器实现类上都加上@Service注解,交由IOC容器管理

测试:

    public static void main(String[] args) {
    //创建Spring IOC容器,开启注解扫码
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext("com.mashibing.dp.intepreter");
        //获取管理类
        ExposeProcessor exposeProcessor= (ExposeProcessor) annotationConfigApplicationContext.getBean("exposeProcessor");
        try {
            exposeProcessor.invoke(new PolicyInfo());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

由于项目非Spring web项目,所以必须启动Spring IOC容器,指定包路径对注解进行扫码,这样才能将类交由容器进行管理,不然获取会为空。

e17ef6ce9d14b8265a62e38c607a873f_bc8f64e4e8584d2c962e7c509ebdf861.png

总结

责任链模式有多种写法,具体需要根据业务场景进行定制化开发。


责任链模式的优点:

降低耦合度。它将请求的发送者和接收者解耦

简化了对象。使得对象不需要知道链的结构。

增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。

增加新的请求处理类很方便。


责任链模式的缺点:

不能保证请求一定被接收。

系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。

可能不容易观察运行时的特征,有碍于除错。


目录
相关文章
|
存储 算法 安全
国密算法及简单使用
国密算法,即国家密码局认定的国产密码算法,主要用于保护国家关键信息基础设施和商业领域的加密通信和数据安全。根据 2019年10月26日第十三届全国人民代表大会常务委员会第十四次会议通过的《中华人民共和国密码法》,国家对密码实行分类管理,密码分为核心密码、普通密码和商用密码
1826 4
|
程序员 编译器 C语言
C语言中的预处理器指令,涵盖其基本概念、常见指令(如`#define`、`#include`、条件编译指令等)、使用技巧及注意事项
本文深入解析C语言中的预处理器指令,涵盖其基本概念、常见指令(如`#define`、`#include`、条件编译指令等)、使用技巧及注意事项,并通过实际案例分析,展示预处理器指令在代码编写与处理中的重要性和灵活性。
579 2
|
Java 网络安全 数据安全/隐私保护
服务器系列之 成功解决 com.jcraft.jsch.JSchException: Auth fail
文章描述了解决在使用JSCH库连接腾讯云服务器时遇到的`com.jcraft.jsch.JSchException: Auth fail`认证失败错误的步骤,包括修改SSH配置文件和重启SSH服务。
服务器系列之 成功解决 com.jcraft.jsch.JSchException: Auth fail
|
算法 Java 数据安全/隐私保护
国密加密算法简介
国密指国家密码局认定的国产密码算法,主要包括SM1、SM2、SM3、SM4等,并持续完善。SM1是对称加密算法,加密强度与AES相当,需加密芯片支持;SM2是非对称加密,基于ECC算法,签名和密钥生成速度优于RSA;SM3为杂凑算法,安全性高于MD5;SM4为对称加密算法,用于无线局域网标准。本文提供使用Java和SpringBoot实现SM2和SM4加密的示例代码及依赖配置。更多国密算法标准可参考国家密码局官网。
2186 1
|
消息中间件 Java BI
使用Java和Spring Batch实现批处理
使用Java和Spring Batch实现批处理
|
Java 微服务 Spring
Spring Boot中获取配置参数的几种方法
Spring Boot中获取配置参数的几种方法
1380 2
|
SQL 前端开发 JavaScript
前端后端技术栈分类和整体架构
前端后端技术栈分类和整体架构
|
安全 架构师 Java
SpringBoot【集成 jasypt】实现配置信息自定义加解密(自定义的属性探测和密码解析器)
SpringBoot【集成 jasypt】实现配置信息自定义加解密(自定义的属性探测和密码解析器)
1842 0
|
存储 Java 关系型数据库
分布式定时任务框架Quartz总结和实践(2)—持久化到Mysql数据库
本文主要介绍分布式定时任务框架Quartz集成SpringBoot持久化数据到Mysql数据库的操作,上一篇文章使用Quartz创建定时任务都是保存在内存中,如果服务重启定时任务就会失效,所以Quartz官方也提供将定时任务等信息持久化到Mysql数据库的功能,本文主要实现这种Quartz的这种使用方式。
2045 0
分布式定时任务框架Quartz总结和实践(2)—持久化到Mysql数据库