责任链设计案例
什么是责任链
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
责任链模式(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的设计。