责任链设计模式
责任链模式
顾名思义,就是链式的去处理一个请求或者任务,收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。

应用场景
- 一个请求需要多种类型的处理
- 各个处理之间,相对独立
- 需要指定多种处理的处理顺序
实际举例
- 打印日志的时候,我们可能定义了多个logger
- Netty在接收和发送数据时,需要经过多个Handler的处理,也是责任链的场景
- 用户登录的时候,需要校验密码、用户状态、是否认证等流程,也是可以采用责任链的场景
- 多条件流程判断:权限控制
- ERP 系统流程审批:总经理、人事经理、项目经理
- Java 过滤器 的底层实现 Filter
如果不使用该设计模式,那么当需求有所改变时代码会变得臃肿或者难以维护。例如一个游戏有100关,我们的代码很可能就会写成这个样子:
if(第1关通过){ // 第2关 游戏 if(第2关通过){ // 第3关 游戏 if(第3关通过){ // 第4关 游戏 if(第4关通过){ // 第5关 游戏 if(第5关通过){ // 第6关 游戏 if(第6关通过){ //... } } } } } }
对上述例子改造
程序结构:

定义链式节点操作:
public interface HandlerChain { /** * 执行下一个链式节点的处理 * @param bizParamDTO * @throws Exception */ void nextNodeDeal(BizParamDTO bizParamDTO) throws Exception; /** * 开始链式节点的处理 * @param bizParamDTO * @return */ ChainResultDTO doChainDeal(BizParamDTO bizParamDTO); }
@Slf4j @Component public class MockHandlerChain implements HandlerChain { SpringUtil springUtil; private final List<Handler> handlers; private Iterator<Handler> iterator; public MockHandlerChain(SpringUtil springUtil) { this.springUtil = springUtil; this.handlers = initFilterList(); this.iterator = this.handlers.iterator(); } private List<Handler> initFilterList() { //获取带类主键@ChainDealPattern的类数组 Object[] handlerFactories = springUtil.getBeansByAnnotation(ChainDealPattern.class); //按order进行排序 List<HandlerProxy> handlerProxies = Arrays.stream(handlerFactories).map(d -> { ChainDealPattern annotation = d.getClass().getAnnotation(ChainDealPattern.class); Handler handle = (Handler) d; HandlerProxy handlerProxy = new HandlerProxy(annotation.order(), handle); return handlerProxy; }).sorted(Comparator.comparing(HandlerProxy::getOrder)).collect(Collectors.toList()); //返回处理的Handler列表 return handlerProxies.stream().map(d -> d.getHandle()).collect(Collectors.toList()); } @Override public void nextNodeDeal(BizParamDTO bizParamDTO) throws Exception { if (this.iterator.hasNext()) { Handler nextHandler = this.iterator.next(); nextHandler.doHandle(bizParamDTO, this); } } @Override public ChainResultDTO doChainDeal(BizParamDTO bizParamDTO) { ChainResultDTO chainResultDTO; try { this.nextNodeDeal(bizParamDTO); chainResultDTO = ChainResultDTO.builder().success(true).build(); } catch (ChainException e) { chainResultDTO = ChainResultDTO.builder().success(false).msg(e.getMsg()).data(bizParamDTO).build(); } catch (Exception e) { log.error(e.getMessage(), e); chainResultDTO = ChainResultDTO.builder().success(false).msg(e.getMessage()).data(bizParamDTO).build(); } return chainResultDTO; } private static final class HandlerProxy { int order; Handler handle; public HandlerProxy(int order, Handler handle) { this.order = order; this.handle = handle; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public Handler getHandle() { return handle; } public void setHandle(Handler handle) { this.handle = handle; } } }
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ChainDealPattern { int order() default 0; String value() default "default"; }
定义:链式的每个节点处理
import com.dt.mvp.myc.service.biz.responsiblechain.chain.HandlerChain; import com.dt.mvp.myc.service.biz.responsiblechain.dto.BizParamDTO; public interface Handler { void doHandle(BizParamDTO parameters, HandlerChain chain) throws Exception; }
第一个节点,判断
@Slf4j @Component @ChainDealPattern(value = "first", order = 50) public class FirstBizHandle implements Handler { @Override public void doHandle(BizParamDTO parameters, HandlerChain chain) throws Exception { log.info("doHandle execute in " + this.getClass()); int limit = 100; if (parameters.getLength() > limit) { throw new ChainException("长度超百"); } //继续执行链式操作 chain.nextNodeDeal(parameters); } }
第二个节点,判断
@Slf4j @Component @ChainDealPattern(value = "second", order = 20) public class SecondBizHandle implements Handler { @Override public void doHandle(BizParamDTO parameters, HandlerChain chain) throws Exception { log.info("doHandle execute in " + this.getClass()); if (parameters.getName() == null) { throw new ChainException("名称不能为空"); } //继续执行链式操作 chain.nextNodeDeal(parameters); } }
第三个节点,判断
@Slf4j @Component @ChainDealPattern(value = "third", order = 30) public class ThirdBizHandle implements Handler { @Override public void doHandle(BizParamDTO parameters, HandlerChain chain) throws Exception { log.info("doHandle execute in " + this.getClass()); if (!parameters.getFlag()) { throw new ChainException("成功标识为假"); } //继续执行链式操作 chain.nextNodeDeal(parameters); } }
第N个节点,判断 。。。
在Service上调用:
@Slf4j @Service @AllArgsConstructor public class BizService { HandlerChain handlerChain; /** * 业务处理,里边采了用链式业务处理 * @param paramDTO * @return */ public ChainResultDTO bizDeal(BizParamDTO paramDTO) { return handlerChain.doChainDeal(paramDTO); } }
浙公网安备 33010602011771号