0%

Tom 商店-基于职责链模式获取购物车详情

在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

下面我们在 Spring 框架的基础上,总结梳理实现动态添加职责链处理器、按指定顺序执行处理器,从而获取购物车详情信息,那么现在开始吧。

首先自定义如下注解,其中 order 属性标识顺序:

1
2
3
4
5
6
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface CartBusiness {
int order() default 0;
}

定义抽象处理器 AbstractBaseHandler:

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> {
private int order;

public int getOrder() {
return order;
}

public void setOrder(int order) {
this.order = order;
}

public abstract boolean doOrder(GetUserCartRequest request, GetUserCartResponse response);
}

分别实现购物车商品配送处理器和购物车商品明细处理器,注解 @CartBusiness 表明该处理器是我们需要执行的处理器,order 表示该处理器的执行顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@CartBusiness(order = 1)
@Component
public class GoodsDeliveryHandler extends AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> {
@Override
public boolean doOrder(GetUserCartRequest request, GetUserCartResponse response) {
System.out.println("购物车商品配送处理器...");
return true;
}
}
@CartBusiness(order = 2)
@Component
public class GoodsDetailHandler extends AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> {
@Override
public boolean doOrder(GetUserCartRequest request, GetUserCartResponse response) {
System.out.println("购物车商品明细处理器...");
return true;
}
}

如下定义职责链处理器 CartInfoChain,CartInfoChain 实现 Spring 框架的 BeanPostProcessor 接口,实现 postProcessAfterInitialization 方法,以从 IOC 容器中获取标有 @CartBusiness 注解的 Bean 按注解中的顺序添加到 handlers 中。其中 execute 方法为职责链执行入口,轮询的执行每个 handler,直到某个 handler 返回 false 则停止执行。

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
@Component
public class CartInfoChain implements BeanPostProcessor {

private List<AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse>> handlers = new ArrayList<>();

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
CartBusiness cartBusiness = AnnotationUtils.findAnnotation(bean.getClass(), CartBusiness.class);
if (cartBusiness != null && bean instanceof AbstractBaseHandler) {
AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> handler = (AbstractBaseHandler) bean;
handler.setOrder(cartBusiness.order());
handlers.add(handler);
sortHandlers();
}
return bean;
}

private void sortHandlers() {
if (!CollectionUtils.isEmpty(handlers)) {
handlers.sort(Comparator.comparingInt(AbstractBaseHandler::getOrder));
}
}

public void execute(GetUserCartRequest request, GetUserCartResponse response) {
for (AbstractBaseHandler<GetUserCartRequest, GetUserCartResponse> handler : handlers) {
boolean next = handler.doOrder(request, response);
if (!next) {
break;
}
}
}
}

执行入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest(classes = SpringBootMainApplication.class)
@RunWith(SpringRunner.class)
public class App {
@Resource
CartInfoChain cartInfoChain;

@Test
public GetUserCartResponse getUserCart(GetUserCartRequest request) {
GetUserCartResponse response = new GetUserCartResponse();
cartInfoChain.execute(request, response);
return response;
}

}
------ 本文结束------