责任链设计案例

责任链设计案例

柳性安 1,923 2023-01-24

责任链设计案例

什么是责任链

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

责任链模式(Chain of Responsibility)是一种处理请求的模式,它让多个处理器都有机会处理该请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递:

     ┌─────────┐
     │ Request │
     └─────────┘
          │
┌ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ┐
          ▼
│  ┌─────────────┐  │
   │ ProcessorA  │
│  └─────────────┘  │
          │
│         ▼         │
   ┌─────────────┐
│  │ ProcessorB  │  │
   └─────────────┘
│         │         │
          ▼
│  ┌─────────────┐  │
   │ ProcessorC  │
│  └─────────────┘  │
          │
└ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ┘
          │
          ▼

案例分享

流程控制器ProcessController

@Slf4j
@Data
public class ProcessController {

    /**
     * 模板映射 由PipelineConfig类初始化属性,默认ProcessTemplate为及时发送类型的普通消息和撤回消息模板
     * 普通消息责任链执行顺序:preParamCheckAction, assembleAction,afterParamCheckAction, sendMqAction
     * 撤回消息责任链执行顺序:assembleAction, sendMqAction
     */
    private Map<String, ProcessTemplate> templateConfig = null;


    /**
     * 执行责任链
     *
     * @param context
     * @return 返回上下文内容
     */
    public ProcessContext process(ProcessContext context) {

        /**
         * 遍历流程节点
         */
        List<BusinessProcess> processList = templateConfig.get(context.getCode()).getProcessList();
        /*
        * 责任链
        */
        for (BusinessProcess businessProcess : processList) {
            businessProcess.process(context);
            if (context.getNeedBreak()) {
                break;
            }
        }
        return context;
    }
}

配置bean

@Configuration
public class PipelineConfig {

    @Autowired
    ......

    /**
     * 普通发送执行流程
     * 1. 前置参数校验
     * 2. 组装参数
     * 3. 后置参数校验
     * 4. 发送消息至MQ
     *
     * @return
     */
    @Bean("commonSendTemplate")
    public ProcessTemplate commonSendTemplate() {
        ProcessTemplate processTemplate = new ProcessTemplate();
        processTemplate.setProcessList(Arrays.asList(
                preParamCheckAction,
                assembleAction,
                afterParamCheckAction,
                sendMqAction));
        return processTemplate;
    }

    /**
     * pipeline流程控制器初始化
     * @return
     */
    @Bean
    public ProcessController processController() {
        ProcessController processController = new ProcessController();
        Map<String, ProcessTemplate> templateConfig = new HashMap<>(4);
        templateConfig.put(BusinessCode.COMMON_SEND.getCode(), commonSendTemplate());
        templateConfig.put(BusinessCode.RECALL.getCode(), recallMessageTemplate());
        processController.setTemplateConfig(templateConfig);
        return processController;
    }

}

流程执行的上下文中介

定义ProcessContext以用于存储流程执行当中需要被引用的属性等。这部分也很重要。

获取流程节点

在ProcessController类当中,拿到流程的各个节点
List<BusinessProcess> processList = templateConfig.get(context.getCode()).getProcessList();

执行责任链

        for (BusinessProcess businessProcess : processList) {
            businessProcess.process(context);//按照执行器链指定的节点执行相应程序
            if (context.getNeedBreak()) {//出错/主动 退出执行
           	 ...
                break;
            }
        }
        return context;

责任链所执行的流程节点接口

/**
 * 业务执行器
 *
 */
public interface BusinessProcess<T extends ProcessModel> {

    /**
     * 真正处理逻辑
     * @param context
     */
    void process(ProcessContext<T> context);
}

具体的流程通过实现该接口,被装载到List<BusinessProcess>流程集合当中,由流程控制器遍历节点执行process里的逻辑。







虽然借鉴了不少大佬的设计经验,但写的还是不那么好,目前自用足矣,借鉴需谨慎,望多多包含;
ps:总结自开源项目Austin的设计。