<>前言
笔者是金融保险行业,有这么一种场景,业务员录完单后提交核保,这时候系统会对保单数据进行校验,如不允许手续费超限校验,客户真实性校验、费率限额校验等等,当校验一多时,维护起来特别麻烦,代码耦合度太高。
这里使用责任链模式,将每个校验模块之间互相独立,在后面新增校验时,只需要往容器中插入即可,且可以给每个模块赋予优选级进行排序,利于管理。与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); } }
* 获取容器中的校验器
* 校验是否往下执行,如果处理器数量为空,或者当前指针已经指向尾部时,则不再往下执行
* 将管理器以及请求参数传递到处理器中进行处理
* 处理器执行完毕后,调用管理器的invoke方法来启动责任链中的下个处理器
<>测试用例
public static void main(String[] args) { ExposeProcessor exposeProcessor=new
ExposeProcessor(); try { exposeProcessor.invoke(new PolicyInfo()); } catch (
Exception e) { e.printStackTrace(); } }
以前代码有很多可以改进的地方,如与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容器,指定包路径对注解进行扫码,这样才能将类交由容器进行管理,不然获取会为空。
<>总结
责任链模式有多种写法,具体需要根据业务场景进行定制化开发。
责任链模式的优点:
* 降低耦合度。它将请求的发送者和接收者解耦
* 简化了对象。使得对象不需要知道链的结构。
* 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
* 增加新的请求处理类很方便。
责任链模式的缺点:
* 不能保证请求一定被接收。
* 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
* 可能不容易观察运行时的特征,有碍于除错。