万字长文!多图!结合DDD讲清楚编写技术方案的七大维度( 四 )

上述代码从功能上完全可以实现业务需求,但是程序员不仅要满足功能,还需要思考代码的可维护性 。如果新增一种订单类型,或者新增一个订单属性处理逻辑,那么我们就要在上述逻辑中新增代码,如果处理不慎就会影响原有逻辑 。
为了避免牵一发而动全身这种情况,设计模式中的开闭原则要求我们面向新增开放,面向修改关闭,我认为这是设计模式中最重要的一条原则 。
需求变化通过扩展,而不是通过修改已有代码实现,这样就保证代码稳定性 。扩展也不是随意扩展,因为事先定义了算法,扩展也是根据算法扩展,用抽象构建框架,用实现扩展细节 。标准意义的二十三种设计模式说到底最终都是在遵循开闭原则 。
如何改变平铺直叙的思考方式?这就要为问题分析加上纵向和横向两个维度,我选择使用分析矩阵方法,其中纵向表示策略,横向表示场景:

万字长文!多图!结合DDD讲清楚编写技术方案的七大维度

文章插图
 
 
3.5.1 纵向做隔离纵向维度表示策略,不同策略在逻辑上和业务上应该是隔离的,本实例包括优惠策略、物流策略和退款策略,策略作为抽象,不同订单类型去扩展这个抽象,策略模式非常适合这种场景 。本文详细分析优惠策略,物流策略和退款策略同理 。
// 优惠策略public interface DiscountStrategy {public void discount(OrderBO orderBO);}// A类型优惠策略@Componentpublic class TypeADiscountStrategy implements DiscountStrategy {@Overridepublic void discount(OrderBO orderBO) {orderBO.setPrice(orderBO.getPrice() * 0.9);}}// B类型优惠策略@Componentpublic class TypeBDiscountStrategy implements DiscountStrategy {@Overridepublic void discount(OrderBO orderBO) {orderBO.setPrice(orderBO.getPrice() * 0.8);}}// C类型优惠策略@Componentpublic class TypeCDiscountStrategy implements DiscountStrategy {@Overridepublic void discount(OrderBO orderBO) {orderBO.setPrice(orderBO.getPrice() * 0.7);}}// 优惠策略工厂@Componentpublic class DiscountStrategyFactory implements InitializingBean {private Map<String, DiscountStrategy> strategyMap = new HashMap<>();@Resourceprivate TypeADiscountStrategy typeADiscountStrategy;@Resourceprivate TypeBDiscountStrategy typeBDiscountStrategy;@Resourceprivate TypeCDiscountStrategy typeCDiscountStrategy;public DiscountStrategy getStrategy(String type) {return strategyMap.get(type);}@Overridepublic void afterPropertiesSet() throws Exception {strategyMap.put(OrderTypeEnum.A_TYPE.getCode(), typeADiscountStrategy);strategyMap.put(OrderTypeEnum.B_TYPE.getCode(), typeBDiscountStrategy);strategyMap.put(OrderTypeEnum.C_TYPE.getCode(), typeCDiscountStrategy);}}// 优惠策略执行@Componentpublic class DiscountStrategyExecutor {private DiscountStrategyFactory discountStrategyFactory;public void discount(OrderBO orderBO) {DiscountStrategy discountStrategy = discountStrategyFactory.getStrategy(orderBO.getType());if (null == discountStrategy) {throw new RuntimeException("无优惠策略");}discountStrategy.discount(orderBO);}}
 
3.5.2 横向做编排横向维度表示场景,一种订单类型在广义上可以认为是一种业务场景,在场景中将独立的策略进行串联,模板方法设计模式适用于这种场景 。
模板方法模式一般使用抽象类定义算法骨架,同时定义一些抽象方法,这些抽象方法延迟到子类实现,这样子类不仅遵守了算法骨架约定,也实现了自己的算法 。既保证了规约也兼顾灵活性,这就是用抽象构建框架,用实现扩展细节 。
// 创建订单服务public interface CreateOrderService {public void createOrder(OrderBO orderBO);}// 抽象创建订单流程public abstract class AbstractCreateOrderFlow {@Resourceprivate OrderMapper orderMapper;public void createOrder(OrderBO orderBO) {// 参数校验if (null == orderBO) {throw new RuntimeException("参数异常");}if (OrderTypeEnum.isNotValid(orderBO.getType())) {throw new RuntimeException("参数异常");}// 计算优惠discount(orderBO);// 计算重量weighing(orderBO);// 退款支持supportRefund(orderBO);// 保存数据OrderDO orderDO = new OrderDO();BeanUtils.copyProperties(orderBO, orderDO);orderMapper.insert(orderDO);}public abstract void discount(OrderBO orderBO);public abstract void weighing(OrderBO orderBO);public abstract void supportRefund(OrderBO orderBO);}// 实现创建订单流程@Servicepublic class CreateOrderFlow extends AbstractCreateOrderFlow {@Resourceprivate DiscountStrategyExecutor discountStrategyExecutor;@Resourceprivate ExpressStrategyExecutor expressStrategyExecutor;@Resourceprivate RefundStrategyExecutor refundStrategyExecutor;@Overridepublic void discount(OrderBO orderBO) {discountStrategyExecutor.discount(orderBO);}@Overridepublic void weighing(OrderBO orderBO) {expressStrategyExecutor.weighing(orderBO);}@Overridepublic void supportRefund(OrderBO orderBO) {refundStrategyExecutor.supportRefund(orderBO);}}


推荐阅读