在说结果之前,让我们看下另一个变化点 。回想下 FetcherExecutor 的执行点,如下:
@Overridepublic List<OrderListVO> getByUserId(Long userId) {List<Order> orders = this.orderRepository.getByUserId(userId);List<OrderListVOFetcherV1> orderDetailVOS = orders.stream().map(order -> new OrderListVOFetcherV1(OrderVO.apply(order))).collect(toList());// 手工调用,OrderListVO 实现新接口,需要增加新的依赖和调用this.addressVOFetcherExecutorV1.fetch(orderDetailVOS);this.productVOFetcherExecutorV1.fetch(orderDetailVOS);this.userVOFetcherExecutorV1.fetch(orderDetailVOS);return orderDetailVOS.stream().collect(toList());}@Overridepublic OrderDetailVO getDetailByOrderId(Long orderId) {Order order = this.orderRepository.getById(orderId);OrderDetailVOFetcherV1 orderDetail = new OrderDetailVOFetcherV1(OrderVO.apply(order));List<OrderDetailVOFetcherV1> orderDetailVOS = Arrays.asList(orderDetail);// 手工调用,OrderDetailVO 实现新接口,需要增加新的依赖和调用this.addressVOFetcherExecutorV1.fetch(orderDetailVOS);this.productVOFetcherExecutorV1.fetch(orderDetailVOS);this.userVOFetcherExecutorV1.fetch(orderDetailVOS);this.payInfoVOFetcherExecutorV1.fetch(orderDetailVOS);return orderDetail;}其实,需要调用哪些 FetcherExecutor 完全可以由 VO 实现的接口来确定 。也就是说 , 需要绑定新数据,只需 VO 继承并实现新的 Fetcher 接口即可 。对此,我们需要:
- 一个统一的访问入口,对外提供访问
- 每个 FetcherExecutor 能够识别 VO 并执行绑定逻辑
答案是:责任链模型
标准的责任链模式用起来比较繁琐,在 Spring 实现中大量使用他的一种变现,及提供一个验证接口,由组件自身完成判断,用于决定是否执行自身逻辑 。
整体设计如下:

文章插图
首先,为了统一 FetcherExecutor 的行为,抽取通用接口:
public interface ItemFetcherExecutor<F extends ItemFetcher> {/*** 该组件是否能处理 cls 类型* @param cls* @return*/boolean support(Class<F> cls);/***执行真正的数据绑定* @param fetchers*/void fetch(List<F> fetchers);}具体的实现,可以见 UserVOFetcherExecutorV2 的 support 方法:【DDD死党:内存Join——将复用和扩展用到极致】
@Overridepublic boolean support(Class<UserVOFetcherV2> cls) {return UserVOFetcherV2.class.isAssignableFrom(cls);}实现逻辑非常简单,只是判断 cls 是否实现了 UserVOFetcherV2 接口 。有了 FetcherExecutor 组件后,接下来就是为其提供统一的访问入口:
@Servicepublic class FetcherService {@Autowiredprivate List<ItemFetcherExecutor> itemFetcherExecutors;public <F extends ItemFetcher> void fetch(Class<F> cls, List<F> fetchers){if (CollectionUtils.isNotEmpty(fetchers)){this.itemFetcherExecutors.stream()// 是否能处理该类型.filter(itemFetcherExecutor -> itemFetcherExecutor.support(cls))// 执行真正的绑定.forEach(itemFetcherExecutor -> itemFetcherExecutor.fetch(fetchers));}}}逻辑即为简单,依次遍历 FetcherExecutor,根据 support 执行结果,执行 fetch 逻辑 。【小常识】Spring 可以将容器中的全部实现直接注入到 List<Bean> 。在上述代码中,将会把所有的 ItemFetcherExecutor 实现注入到 itemFetcherExecutors 属性 。因此,在新增 FetcherExecutor 时,只需将其声明为 Spring Bean,无需调整代码逻辑 。
OK,我们有了 FetcherService 提供统一的数据绑定能力,原来 OrderServiceFetcher 中 fetch 操作的变化点转移到 FetcherService , 自身变得非常稳定 。具体如下:
@Servicepublic class OrderServiceFetcherV2 implements OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate FetcherService fetcherService;@Overridepublic List<OrderListVO> getByUserId(Long userId) {List<Order> orders = this.orderRepository.getByUserId(userId);List<OrderListVOFetcherV2> orderDetailVOS = orders.stream().map(order -> new OrderListVOFetcherV2(OrderVO.apply(order))).collect(toList());// VO 数据绑定发生变化,只需调整 VO 实现接口,此处无需变化fetcherService.fetch(OrderListVOFetcherV2.class, orderDetailVOS);return orderDetailVOS.stream().collect(toList());}@Overridepublic OrderDetailVO getDetailByOrderId(Long orderId) {Order order = this.orderRepository.getById(orderId);OrderDetailVOFetcherV2 orderDetail = new OrderDetailVOFetcherV2(OrderVO.apply(order));// VO 数据绑定发生变化,只需调整 VO 实现接口,此处无需变化fetcherService.fetch(OrderDetailVOFetcherV2.class, Arrays.asList(orderDetail));return orderDetail;}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 能如何看电脑内存,如何查看电脑c盘和d盘内存
- 你知道怎样在 Python 中管理内存吗
- 如何查看手机运行内存大小,如何查看手机软件占用的内存
- 能咋滴看电脑内存,怎么查看自己电脑内存多大
- sd卡和内存卡有什么区别
- 电脑能插3根内存条,电脑能咋滴共存两个窗口
- 苹果手机怎么在电脑上清理内存,苹果手机怎样可以清理内存拉圾
- oppo reno ace能插内存卡吗
- 手机内存满了该怎么处理,手机里照片太多,占内存太多该怎么办?
- 能咋地看电脑内存,如何查看电脑的内存条型号大小
