开门见山
某天,我在公园散步打开手机 JD 发现 GTX 3080 TI 显卡上架,正准备付款的时候我看看我的订单详情,就联想到了我以前做的一个订单详情处理的业务。具体的伪代码如下:
public Map<String, List<Object>> doHandler(List<Object> dataList) { Map<String, List<Object>> resultMap = new HashMap<>(); // 实物商品 if (实物商品) { // 数据处理 ... resultMap.put("inKindList", mainList); } // 虚拟商品 if (虚拟商品) { // 数据处理 ... resultMap.put("virtualList", tradeList); } // 其他商品 if (其他商品) { // 数据处理 ... resultMap.put("otherList", otherList); } return resultMap; }
业务描述
上面我只是简单的对我的数据处理方法做了一个伪代码的表述。对于这种场景就非常类似京东购物下单的情况。
比如:最近618 搞活动我在需要在京东购买一张 GTX 3038 TI 显卡,包含 2 年的质保服务。送一个机械键盘,再加 500 数码品类的优惠券(两张 200 的,一张 100 ),自动关注该店铺送 VIP 不定期推送该店铺活动。我直接购买我的订单假设只有这一个商品。
再把这个场景套回到我的伪代码中。
那么订单详情中主要的信息就可以分为三部分
- 商品的主要信息包含: GTX 3038 TI 显卡, 2 年的质保服务
- 赠送实物和优惠券:赠送机械键盘,再加 500 数码品类。
- 其他辅助信息:比如订单成为某店铺的 VIP , 订阅该店铺活动等。
数据结构
假设我上面提及到的所有订单详情记录都是存储在 order_detail 表中,并且每一订单实物、虚拟商品都存为一条数据。并且我在回显的时候需要做一个分类处理,需要分为三类:商品信息(显卡、质保信息),实物赠送(机械键盘)、优惠券、其他。他们都存在实际价格、优惠价格、原价等。
业务需求
相当于我的需求就是需要将这些商品的价值分别展示在订单详情中,只要是用户在没有支付之前这些这些商品的信息可能都会发生变化,都需要进行实时的计算(个人觉得如果是热点商品肯定这些都是提前预热好的,不能去实时计算的,为了贴合场景咱们假设一下)。
代码设计
在代码设计之前我们先来看看我的设计, 如下图所示:
为什么是命令模式?
命令模式:它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
适用场景:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
对于“订单详情” 的这个场景,咱们就可以确定三个分类:主要信息(实物商品)、虚拟商品(优惠券等)、其他商品。这个可以分别对应三个数据处理命令类。
我的代码
我的代码如下,主要是解决订单详情中的信息进行分类显示的问题。
命令接口和参数定义
命令接口如下:
/** * 订单详情处理 */ public interface OrderDetailService { Map<String, List<OrderDetailDto>> orderDetailProcess(List<OrderDetailDto> orderDetailList); }
OrderDetailDto
的处理如下:
/** * 订单详情 */ @Data public class OrderDetailDto { private Long id; /** * 订单编码 */ private String orderCode; /** * 商品编码 */ private String commodityCode; /** * 商品名称 */ private Integer commodityType; /** * 商品名称 */ private String commodityName; /** * 单价 */ private BigDecimal commodityUnitPrice; /** * 商品数量 */ private Integer commodityQuantity; /** * 原价 */ private BigDecimal originalPrice; /** * 折扣价格 */ private BigDecimal discountPrice; /** * 实际价格 */ private BigDecimal actualPrice; }