0%

Tom 商店-基于模板方法模式实现订单取消

Tom 商店-基于策略模式实现订单创建 一文中我们介绍了基于策略模式来实现不同类型的订单创建流程。同样,不同类型的订单的取消逻辑也有所不同,而对于取消订单的公共逻辑部分我们则抽取到抽象类中实现,对于具体的取消逻辑则有各自的子类去实现,这里我们使用了模板方法模式实现。为了流程的连贯,我们这里同时也使用到了策略模式实现动态切换不同类型的取消订单实现类。

首先,我们先定义如下策略接口 CancelOrderService:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 订单取消策略接口
*/
public interface CancelOrderService {

/**
* 获取取消订单的类型
* @return
*/
Integer getCancelOrderType();

/**
* 策略接口,具体不同类型订单取消逻辑由子类实现
* @param request
* @param orderDTO
*/
void cancelOrder(CancelOrderRequest request, OrderDTO orderDTO);
}

接着定义普通订单和虚拟订单的订单取消策略实现,具体如下所示:

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
@Service
public class CancelNormalOrderOrderServiceImpl implements CancelOrderService {

@Override
public Integer getCancelOrderType() {
return OrderTypeEnum.NORMAL.val();
}

@Override
public void cancelOrder(CancelOrderRequest request, OrderDTO orderDTO) {
// ...
}
}

@Service
public class CancelVirtualOrderOrderServiceImpl implements CancelOrderService {

@Override
public Integer getCancelOrderType() {
return OrderTypeEnum.VIRTUAL.val();
}

@Override
public void cancelOrder(CancelOrderRequest request, OrderDTO orderDTO) {
//...
}
}

我们实现如下策略工厂,其中 getCancelOrderService 支持根据传入的订单类型 orderType 获取到 CancelNormalOrderOrderServiceImpl 或者 CancelVirtualOrderOrderServiceImpl,其原理是策略工厂 CancelOrderServiceFactory 实现 InitializingBean 接口并重写了 afterPropertiesSet,以实现从 IOC 容器中获取到 CancelOrderService 策略接口的实现类并存入到 cancelServiceMap 中。

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
@Component
public class CancelOrderServiceFactory implements InitializingBean {

/**
* 框架自动注入 CancelOrderService 的实现类
*/
@Autowired
private List<CancelOrderService> cancelOrderServices;

private Map<Integer, CancelOrderService> cancelServiceMap = new HashMap<>();

@Override
public void afterPropertiesSet() {
if (CollectionUtil.isNotEmpty(cancelOrderServices)) {
for (CancelOrderService service : cancelOrderServices) {
cancelServiceMap.put(service.getCancelOrderType(), service);
}
}
}

/**
* 工厂方法获取不同类型的取消订单 service
* @param orderType
* @return
*/
public CancelOrderService getCancelOrderService(Integer orderType) {
return cancelServiceMap.get(orderType);
}

}

我们可以使用如下代码动态调用不同类型的订单取消 service:

1
2
3
4
5
6
@Test
public void cancelOrder() {
CancelOrderRequest request = new CancelOrderRequest();
OrderDTO orderDTO = getOrderDTO(request);
cancelOrderServiceFactory.getCancelOrderService(orderDTO.getOrderType()).cancelOrder(request, orderDTO);
}

下面我们再讲解订单取消中涉及到的模板方法模式的使用,首先定义如下抽象类,executeCancel 是不同类型的订单取消的公共入口,该方法调用了模板方法 execute,注意该方法并没有实现,而只是提供了方法的定义。在调用模板方法 execute 之前,我们可以调用所有订单类型订单取消的公共逻辑,例如订单状态为待支付时,同一调用 rollbackIfOnUnpaid 方法。

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
/**
* 抽象订单取消服务
*/
public abstract class AbsCancelOrderService {

/**
* 执行订单取消入口
* @param request
* @param orderDTO
*/
protected void executeCancel(CancelOrderRequest request, OrderDTO orderDTO) {
// 处理公共逻辑,例如订单待支付订单取消回滚
Integer orderStatus = orderDTO.getOrderStatus();
if (Objects.equals(orderStatus, OrderStatusEnum.PREPAY)) {
rollbackIfOnUnpaid(request, orderDTO);
return;
}
// 调用模板方法
execute(request, orderDTO);
}

/**
* 订单取消执行模板方法,具体取消订单执行逻辑由子类实现
* @param request
* @param orderDTO
*/
protected abstract void execute(CancelOrderRequest request, OrderDTO orderDTO);

/**
* 待支付订单取消回滚公共逻辑
* @param request
* @param orderDTO
*/
protected void rollbackIfOnUnpaid(CancelOrderRequest request, OrderDTO orderDTO) {
// ...
}

}

接着我们只需让 CancelNormalOrderOrderServiceImpl 和 CancelVirtualOrderOrderServiceImpl 类继承 AbsCancelOrderService 并重写 execute,并让 cancelOrder 调用父类的 executeCancel 方法即可。如下:

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
@Service
public class CancelNormalOrderOrderServiceImpl extends AbsCancelOrderService implements CancelOrderService {

@Override
protected void execute(CancelOrderRequest request, OrderDTO orderDTO) {
System.out.println("执行普通订单取消");
}

@Override
public Integer getCancelOrderType() {
return OrderTypeEnum.NORMAL.val();
}

@Override
public void cancelOrder(CancelOrderRequest request, OrderDTO orderDTO) {
executeCancel(request, orderDTO);
}
}

@Service
public class CancelVirtualOrderOrderServiceImpl extends AbsCancelOrderService implements CancelOrderService {

@Override
protected void execute(CancelOrderRequest request, OrderDTO orderDTO) {
System.out.println("执行虚拟订单取消");
}

@Override
public Integer getCancelOrderType() {
return OrderTypeEnum.VIRTUAL.val();
}

@Override
public void cancelOrder(CancelOrderRequest request, OrderDTO orderDTO) {
execute(request, orderDTO);
}
}
------ 本文结束------