责任链设计模式
责任链设计模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。责任链模式通过将这些对象连成一条链,并沿着这条链传递请求,直到某个对象处理它为止。
1. 基础代码示例
/*** cyt 20240814 根据参数查找运费模板* @param waybillDTO * @return 运费模板实体*/private CarriageEntity findCarriage(WaybillDTO waybillDTO) {// 1. 如果是同城。。。处理逻辑。。。return carriageEntity;// 2. 如果是同省。。。处理逻辑。。。return carriageEntity;// 3. 如果是经济区。。。处理逻辑。。。return carriageEntity;// 4. 跨省。。。处理逻辑。。。return carriageEntity;}
在上述的代码中,判断了很多种情况,如果后续要再增加不同类型的模板或者调整模板之间的优先级,就必须改动代码,所以这样的实现扩展性并不好,也不够灵活。这里可以通过【责任链设计模式】来优化。
之所以采用【责任链】模式,是因为在查找模板时,不同的模板处理逻辑不同,并且这些逻辑组成了一条处理链,有开头有结尾,只要能找到符合条件的模板即结束。
2.责任链模式优化代码
2.1 定义处理链抽象类
1. nextHandler:记录下一个处理器
2. setNextHandler:给nextHander赋值
3. doHandler:抽象方法,由具体的处理器实现,用于处理运费模板的查找逻辑
4、doNextHander:已经实现好的,调用下一个处理器的方法
/*** 运费模板处理链的抽象定义*/
public abstract class AbstractCarriageChainHandler {private AbstractCarriageChainHandler nextHandler;/*** 执行过滤方法,通过输入参数查找运费模板** @param waybillDTO 输入参数* @return 运费模板*/public abstract CarriageEntity doHandler(WaybillDTO waybillDTO);/*** 执行下一个处理器** @param waybillDTO 输入参数* @param carriageEntity 上个handler处理得到的对象* @return*/protected CarriageEntity doNextHandler(WaybillDTO waybillDTO, CarriageEntity carriageEntity) {if (nextHandler == null || carriageEntity != null) {//如果下游Handler为空 或 上个Handler已经找到运费模板就返回return carriageEntity;}return nextHandler.doHandler(waybillDTO);}/*** 设置下游Handler** @param nextHandler 下游Handler*/public void setNextHandler(AbstractCarriageChainHandler nextHandler) {this.nextHandler = nextHandler;}
}
2.2 实现具体的处理器
定义顺序,继承处理链抽象类,实现doHander抽象方法,在doHander最后返回doNextHander。
2.2.1 同城寄
/*** 同城寄*/
@Order(100) //定义顺序
@Component
public class SameCityChainHandler extends AbstractCarriageChainHandler {@Overridepublic CarriageEntity doHandler(WaybillDTO waybillDTO) {。。。处理逻辑。。。return doNextHandler(waybillDTO, carriageEntity);}
}
2.2.2 省内寄
/*** 省内寄*/
@Order(200) //定义顺序
@Component
public class SameProvinceChainHandler extends AbstractCarriageChainHandler {@Overridepublic CarriageEntity doHandler(WaybillDTO waybillDTO) {。。。处理逻辑。。。return doNextHandler(waybillDTO, carriageEntity);}
}
2.2.3 经济区互寄
/*** 经济区互寄*/
@Order(300) //定义顺序
@Component
public class EconomicZoneChainHandler extends AbstractCarriageChainHandler {@Overridepublic CarriageEntity doHandler(WaybillDTO waybillDTO) { 。。。处理逻辑。。。return doNextHandler(waybillDTO, carriageEntity);}
}
2.2.4 跨省寄
/*** 跨省*/
@Order(400) //定义顺序
@Component
public class TransProvinceChainHandler extends AbstractCarriageChainHandler { @Overridepublic CarriageEntity doHandler(WaybillDTO waybillDTO) {。。。处理逻辑。。。return doNextHandler(waybillDTO, carriageEntity);}
}
2.3 组装处理链
组装处理链,按照@Order注解中的值,由小到大排序。
/*** 查找运费模板处理链 @Order注解指定handler顺序*/
@Component
public class CarriageChainHandler {/*** 利用Spring注入特性,按照 @Order 从小到达排序注入到集合中*/@Resourceprivate List<AbstractCarriageChainHandler> chainHandlers;private AbstractCarriageChainHandler firstHandler;/*** 组装处理链*/@PostConstruct // Spring自动调用该方法private void constructChain() {if (CollUtil.isEmpty(chainHandlers)) {throw new SLException("not found carriage chain handler!");}//处理链中第一个节点firstHandler = chainHandlers.get(0);for (int i = 0; i < chainHandlers.size(); i++) {if (i == chainHandlers.size() - 1) {//最后一个处理链节点chainHandlers.get(i).setNextHandler(null);} else {//设置下游节点chainHandlers.get(i).setNextHandler(chainHandlers.get(i + 1));}}}public CarriageEntity findCarriage(WaybillDTO waybillDTO) {//从第一个节点开始处理return firstHandler.doHandler(waybillDTO);}}
@PostConstruct:这个注解标注的方法会在 Spring 完成依赖注入后自动调用,用来初始化责任链。
3. 总结
调用carriageChainHandler.findCarriage(waybillDTO)方法和直接调用基础代码示例中的findCarriage(waybillDTO)方法,效果相同,完成了责任链模式的代码优化。
通过这种设计,如果将来需要新增处理逻辑或调整处理顺序,只需新建处理器类或调整 @Order 注解的值,而无需修改现有的代码结构,极大地提高了代码的可维护性和扩展性。
