设计模式-总览
https://mp.csdn.net/mp_blog/creation/editor/122202507一、订单系统完成订单方法使用模板方法模式
1、背景介绍
发现线上和线下订单,其实逻辑都差不多,却写了两套差不多相同的东西。于是决定重构一下,方法如下:
@Transactional(rollbackFor = Exception.class)
public void completeOrder(DanluOrderCompleteVO complete) {
BusinessAsserts.notNull(complete, DepotNextDoorExceptions.Order.ILLEGAL_ERROR);
BusinessAsserts.notBlank(complete.getOrderCode(), DepotNextDoorExceptions.Order.ILLEGAL_ERROR);
String orderCode = complete.getOrderCode();
Order order = orderRepository.findByOrderCode(orderCode);
order.setStatus(OrderStatus.FINISHED);
order.setCompleteTime(new Timestamp(System.currentTimeMillis()));
try {
orderRepository.save(order);
} catch (Exception e) {
logger.error("更新订单状态失败:{}", e);
throw new DepotNextDoorException(500, "订单状态更新失败");
}
}
@Transactional(rollbackFor = Exception.class)
public void completeOnlineOrder(CompleteOnlineOrderReqVO reqVO) {
logger.info("订单确认收货:{}", JSON.toJSONString(reqVO));
BusinessAsserts.notNull(reqVO, DepotNextDoorExceptions.Order.ILLEGAL_ERROR);
Order order = null;
if (Objects.nonNull(reqVO.getOrderId())) {
order = orderRepository.findOne(reqVO.getOrderId());
}
if (StringUtils.isNotBlank(reqVO.getOrderCode())) {
order = orderRepository.findByOrderCode(reqVO.getOrderCode());
}
BusinessAsserts.notNull(order, DepotNextDoorExceptions.Order.ORDER_NOT_EXIST);
if(order.getStatus().equals(OrderStatus.DELIVERED) &&
!Objects.equals(order.getOrderChannel(), OrderChannelEnum.MANAGE)){
try {
order.setStatus(OrderStatus.FINISHED);
order.setCompleteTime(new Timestamp(System.currentTimeMillis()));
orderRepository.save(order);
logger.info("已将订单状态调整为已完成:订单号:{}", reqVO.getOrderCode());
} catch (Exception e) {
logger.error("该订单完结状态更新异常", e);
}
} else {
logger.error("该订单状态无法完结:请求信息:{}", JSON.toJSONString(reqVO));
}
}
2、分析
1、入参并不相同(历史原因不想改该部分),但是都只使用了订单编码查数据库订单信息,或者传入订单id或者编码
2、保存异常时处理方式却不同,分析应该是都打印日志,然后抛出异常进行回滚
3、不同之处就在获取订单后的验证,有一个需要验证订单渠道类型
4、分析模板步骤为:1)、打印日志;2)、验证参数(可进行省略);3)、获取订单并进行验证;4)、验证订单状态(相同的 部分放父类);5、持久化修改订单状态
3、重构
于是重构后 父模板类,validCompleteOrder方法是唯一不同的处理部分,使用空方法让子类重新,如下:
/**
* 完成订单模板
*
* @param orderId 订单id
* @param orderCode 订单编码
*/
public final void completeOrder(Long orderId, String orderCode) {
// 1、打印日志
logger.info("订单确认收货: orderId:{},orderCode:{}", orderId, orderCode);
// 2、验证参数(可进行省略)
// 3、获取订单
Order order = null;
if (Objects.nonNull(orderId)) {
order = orderRepository.findOne(orderId);
}
if (StringUtils.isNotBlank(orderCode)) {
order = orderRepository.findByOrderCode(orderCode);
}
// 4、验证订单状态(相同的部分放父类)
BusinessAsserts.notNull(order, DepotNextDoorExceptions.Order.ORDER_NOT_EXIST);
BusinessAsserts.isTrue(Objects.equals(OrderStatus.DELIVERED, order.getStatus()),
DepotNextDoorExceptions.Order.ORDER_STATUS_CAN_NOT_COMPLETE);
validCompleteOrder(order.getOrderChannel());
// 5、保存订单信息
order.setStatus(OrderStatus.FINISHED);
order.setCompleteTime(new Timestamp(System.currentTimeMillis()));
try {
orderRepository.save(order);
logger.info("已将订单状态调整为已完成:订单号:{}", order.getOrderCode());
} catch (Exception e) {
logger.error("该订单完结状态更新异常", e);
throw new DepotNextDoorException(500, "订单状态更新失败");
}
}
/**
* 验证订单状态和信息,子类必须实现
*/
protected void validCompleteOrder(OrderChannelEnum channelEnum) {
}
子类重构后为:
@Override
@Transactional(rollbackFor = Exception.class)
public void completeOnlineOrder(CompleteOnlineOrderReqVO reqVO) {
BusinessAsserts.notNull(reqVO, DepotNextDoorExceptions.Order.ILLEGAL_ERROR);
super.completeOrder(reqVO.getOrderId(), reqVO.getOrderCode());
}
@Override
protected void validCompleteOrder(OrderChannelEnum channelEnum) {
BusinessAsserts.isTrue(OrderChannelEnum.MANAGE.equals(channelEnum),
DepotNextDoorExceptions.Order.ORDER_STATUS_CAN_NOT_COMPLETE);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void completeOrder(DanluOrderCompleteVO complete) {
super.completeOrder(null, complete.getOrderCode());
}
后续再添加 项目中使用的例子,一个设计模式就是多用几次,穷举,就知道了。个人理解