带你读《2022技术人的百宝黑皮书》——谈一谈凑单页的那些优雅设计(5)https://developer.aliyun.com/article/1338377?groupCode=taobaotech
入参都是统一的context,其中的data为需要拼装的数据。类图如下
MuchContext(多值的数据拼装上下文),data是个集合
1 |
public class MuchContext<D extends ContextData> implements Context { |
|
2 |
||
3 |
|
protected List<D> data; |
4 |
|
|
5 |
|
public void addData(D d) { |
6 |
|
if (CollectionUtils.isEmpty(this.data)) { |
7 |
|
this.data = Lists.newArrayList(); |
8 |
|
} |
9 |
|
this.data.add(d); |
10 |
|
} |
11 |
|
|
12 |
|
public List<D> getData() { |
13 |
|
if (Objects.isNull(this.data)) { |
14 |
|
this.data = Lists.newArrayList(); |
15 |
|
} |
16 |
|
return this.data; |
17 |
|
} |
18 |
} |
|
19 |
|
|
OneContext(单值的数据拼装上下文),data是个对象
public class OneContext <D extends ContextData> implements Context { protected D data; }
各域可根据自己需要实现,各个实现的context也使用了领域模型的思想,将对入参的一些操作封装在此,简化各个命令处理器的获取成本。举个例子,比如入参是一系列操作集合 List handle。但实际使用是需要区分各个操作,那我们就需要在context中做好初始化,方便获取:
1 |
|
private void buildHandle() { |
2 |
// 勾选操作集合 |
|
3 |
|
this.checkedHandleMap = Maps.newHashMap(); |
4 |
|
// 去勾选操作集合 |
5 |
|
this.nonCheckedHandleMap = Maps.newHashMap(); |
6 |
|
// 修改操作集合 |
7 |
|
this.modifyHandleMap = Maps.newHashMap(); |
8 |
|
Optional.ofNullable(requestContext.getExtParam()) |
9 |
|
.map(CartExtParam::getHandle) |
10 |
|
.ifPresent(o -> o.forEach(v -> { |
11 |
|
if (Objects.equals(v.getType(), CartHandleType.checked)) { |
12 |
|
checkedHandleMap.put(v.getCartId(), v); |
13 |
|
} |
14 |
|
if (Objects.equals(v.getType(), CartHandleType.nonChecked)) { |
15 |
|
nonCheckedHandleMap.put(v.getCartId(), v); |
16 |
|
} |
17 |
|
if (Objects.equals(v.getType(), CartHandleType.modify)) { |
18 |
|
modifyHandleMap.put(v.getCartId(), v); |
19 |
|
} |
20 |
|
})); |
21 |
} |
|
下面来看各个命令处理器,类图如下:
命令处理器主要分为SingleCommand和CommonCommand,CommonCommand为普通类型,即将data交与 各个命令自行处理,而SingleCommand则是针对批量处理的情况下,将data集合提前拆好。两个核心区别就在于 一个在框架层执行data的循环,一个是在各个命令层处理循环。主要作用在于:
- SingleCommand减少重复循环代码
- CommonCommand针对下游需要批量处理的可提高性能
下面来看各个命令处理器,类图如下:
public class CouponCustomCommand implements CommonCommand<CartContext> { @Override public boolean check(CartContext context) { // 如果不是跨店满减或者品类券,不进行该命令处理 return Objects.equals(BenefitEnum.kdmj, context.getRequestContext().getCouponData().getBen- efitEnum()) || Objects.equals(BenefitEnum.plCoupon, context.getRequestContext().getCouponData().get- BenefitEnum()); } @Override public boolean execute(CartContext context) { CartData cartData = context.getData(); // 命令处理return true; }
最终的成品如下,各个命令执行顺序一目了然
带你读《2022技术人的百宝黑皮书》——谈一谈凑单页的那些优雅设计(7)https://developer.aliyun.com/article/1338375?groupCode=taobaotech