技术设计模式责任链模式
penjc什么是责任链模式
在责任链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条,链条上的每个处理器各自承担各自的处理职责。
责任链模式优点
责任链模式的优点在于,它可以动态地添加、删除和调整处理者对象,从而灵活地构建处理链。同时,它也避免了请求发送者和接收者之间的紧耦合,增强了系统的灵活性和可扩展性。
责任链模式实现
以购票为例,在实际购票业务场景中,用户发起一次购票请求后,购票接口在真正完成创建订单和扣减余票行为前,需要验证当前请求中的参数是否正常请求,或者说是否满足购票情况。
- 购票请求用户传递的参数是否为空,比如:车次 ID、乘车人、出发站点、到达站点等。
- 购票请求用户传递的参数是否正确,比如:车次 ID 是否存在、出发和到达站点是否存在等。
- 需要购票的车次是否满足乘车人的数量,也就是列车对应座位的余量是否充足。
- 乘客是否已购买当前车次,或者乘客是否已购买当天时间冲突的车次。
解决前置校验需求需要实现一堆逻辑,常常需要写上几百上千行代码。并且,上面的代码不具备开闭原则,以及代码扩展性,整体来说复杂且臃肿。
为了避免这种坏代码味道,我们可以运用责任链设计模式,对购票验证逻辑进行抽象。
1.定义责任链基本接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public interface AbstractChainHandler<T> extends Ordered {
void handler(T requestParam);
String mark(); }
|
org.springframework.core.Ordered 是Spring框架中的一个接口,它被用于那些需要在容器中定义执行顺序的组件。在Spring中,有许多场景可能需要按照特定的顺序来执行或初始化Bean,比如拦截器(Interceptors)、过滤器(Filters)、后置处理器(PostProcessors)等。
2.定义购票过滤接口
1 2 3 4 5 6 7 8 9 10
|
public interface TrainPurchaseTicketChainFilter<T extends PurchaseTicketReqDTO> extends AbstractChainHandler<PurchaseTicketReqDTO> {
@Override default String mark() { return TicketChainMarkEnum.TRAIN_PURCHASE_TICKET_FILTER.name(); } }
|
3.实现列车购买过滤器实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
@Component public class TrainPurchaseTicketParamNotNullChainHandler implements TrainPurchaseTicketChainFilter<PurchaseTicketReqDTO> {
@Override public void handler(PurchaseTicketReqDTO requestParam) { }
@Override public int getOrder() { return 0; } }
@Component @RequiredArgsConstructor public class TrainPurchaseTicketParamVerifyChainHandler implements TrainPurchaseTicketChainFilter<PurchaseTicketReqDTO> {
private final TrainMapper trainMapper; private final TrainStationMapper trainStationMapper; private final DistributedCache distributedCache;
@Override public void handler(PurchaseTicketReqDTO requestParam) { }
@Override public int getOrder() { return 10; } }
@Component @RequiredArgsConstructor public class TrainPurchaseTicketParamStockChainHandler implements TrainPurchaseTicketChainFilter<PurchaseTicketReqDTO> {
private final SeatMarginCacheLoader seatMarginCacheLoader; private final DistributedCache distributedCache;
@Override public void handler(PurchaseTicketReqDTO requestParam) { }
@Override public int getOrder() { return 20; } }
@Component @RequiredArgsConstructor public class TrainPurchaseTicketRepeatChainHandler implements TrainPurchaseTicketChainFilter<PurchaseTicketReqDTO> {
@Override public void handler(PurchaseTicketReqDTO requestParam) { }
@Override public int getOrder() { return 30; } }
|
4.购票流程使用过滤器
1 2 3 4 5 6 7 8 9 10
| private final AbstractChainContext<PurchaseTicketReqDTO> purchaseTicketAbstractChainContext;
@Override @Transactional(rollbackFor = Throwable.class) public TicketPurchaseRespDTO purchaseTickets(PurchaseTicketReqDTO requestParam) { purchaseTicketAbstractChainContext.handler(TicketChainMarkEnum.TRAIN_PURCHASE_TICKET_FILTER.name(), requestParam); }
|
购票责任链实现原理
1.运行时获取责任链具体实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
public final class AbstractChainContext<T> implements CommandLineRunner {
private final Map<String, List<AbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();
public void handler(String mark, T requestParam) { List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark); if (CollectionUtils.isEmpty(abstractChainHandlers)) { throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark)); } abstractChainHandlers.forEach(each -> each.handler(requestParam)); }
@Override public void run(String... args) throws Exception { Map<String, AbstractChainHandler> chainFilterMap = ApplicationContextHolder .getBeansOfType(AbstractChainHandler.class); chainFilterMap.forEach((beanName, bean) -> { List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(bean.mark()); if (CollectionUtils.isEmpty(abstractChainHandlers)) { abstractChainHandlers = new ArrayList(); } abstractChainHandlers.add(bean); List<AbstractChainHandler> actualAbstractChainHandlers = abstractChainHandlers.stream() .sorted(Comparator.comparing(Ordered::getOrder)) .collect(Collectors.toList()); abstractChainHandlerContainer.put(bean.mark(), actualAbstractChainHandlers); }); } }
|
2.初始化责任链容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public final class AbstractChainContext<T> implements CommandLineRunner {
private final Map<String, List<AbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();
@Override public void run(String... args) throws Exception { Map<String, AbstractChainHandler> chainFilterMap = ApplicationContextHolder .getBeansOfType(AbstractChainHandler.class); chainFilterMap.forEach((beanName, bean) -> { List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(bean.mark()); if (CollectionUtils.isEmpty(abstractChainHandlers)) { abstractChainHandlers = new ArrayList(); } abstractChainHandlers.add(bean); List<AbstractChainHandler> actualAbstractChainHandlers = abstractChainHandlers.stream() .sorted(Comparator.comparing(Ordered::getOrder)) .collect(Collectors.toList()); abstractChainHandlerContainer.put(bean.mark(), actualAbstractChainHandlers); }); } }
|