34

【一起学设计模式】状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经...

 4 years ago
source link: http://www.cnblogs.com/wang-meng/p/12038619.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言

之前在我的博客(一枝花算不算浪漫)中已经更新过两篇设计模式相关的内容

上面内容都是基于真实业务场景精简后的设计( 工作中真实场景使用到的 )。

之前为了学习设计模式,看过网上很多相关博客讲解,大都是画下UML类图,举例几个毫不相干的demo,看了几遍仍然是云里雾里。

因为自己现在做的项目就是属于B2C的商城,项目中使用到了大量的设计模式,所以这里精简真实的业务场景,将核心的业务代码抽离出来。代码不涉及任何公司信息,所有敏感信息都已屏蔽,代码只用作学习交流使用。

业务场景

一图流,首先看下提交订单 我们抽象出的一些场景:

7bEVRf2.jpg!web

订单中心:

1、订单中心创建订单

2、订单状态流转(状态模式)

3、记录操作日志(装饰器模式+简单工厂模式)

4、订单中心通知 库存中心更新库存

调度中心:

1、库存中心更新本地库存(使用命令模式+模板方法模式+工厂模式)

这个上讲已经说过: 【一起学设计模式】命令模式+模板方法+工厂方法实战: 如何优雅的更新商品库存...

2、将更新库存数据放到消息中,调度中心消费消息(中介模式)

3、放入消息队列中,判断队列是否放满了,如果放满了需要建立离线存储(备忘录模式)

4、异步监听消息处理结果(观察者模式)

这个模型应该很简单,我们来一步步拆解 一步步代码分析

订单状态流转 + 操作日志记录

代码实现

  1. 订单中心提交订单操作

    /**
    * 订单状态管理器
    */
    @Autowired
    private LoggedOrderStateManager orderStateManager;
    
    public OrderInfoDTO save(OrderInfoDTO order) throws Exception {
        // 检查库存是否充足
        if(!isStockEnough(order)) {
            return order;
        }
    
        // 将订单信息保存到本地数据库
        saveOrder(order);
        // 订单状态流转
        orderStateManager.create(order); 
    
        // other logic
        return order;
    }
  2. 订单状态管理器

    /**
     * 会自动记录日志的订单状态管理器
     * @author wangmeng
     *
     */
    @Component
    public class LoggedOrderStateManager implements OrderStateManager {
    
        /**
         * 订单状态管理器
         */
        @Autowired
        private OrderStateManagerImpl orderStateManager;
    
        /**
         * 订单操作日志DAO组件
         */
        @Autowired
        private OrderOperateLogDAO orderOperateLogDAO;
    
        /**
         * 订单操作内容工厂
         */
        @Autowired
        private OrderOperateLogFactory orderOperateLogFactory;
    
        @Override
        public void create(OrderInfoDTO order) throws Exception {
            orderStateManager.create(order); 
            orderOperateLogDAO.save(orderOperateLogFactory.get(order, OrderOperateType.CREATE_ORDER));      
        }
    
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return orderStateManager.canCancel(order);
        }
    
        @Override
        public void cancel(OrderInfoDTO order) throws Exception {
            orderStateManager.cancel(order); 
            orderOperateLogDAO.save(orderOperateLogFactory.get(order, OrderOperateType.CANCEL_ORDER)); 
        }
    }
  3. 日志操作工厂

    /**
     * 订单操作内容工厂
     * @author wangmeng
     *
     */
    @Component
    public class OrderOperateLogFactory {
    
        /**
         * 日期辅助组件
         */
        @Autowired
        private DateProvider dateProvider;
    
        /**
         * 获取订单操作内容
         * @param operateType 订单操作类型
         * @return 订单操作内容
         */
        public OrderOperateLogDO get(OrderInfoDTO order, Integer operateType) throws Exception {
            String operateContent = null;
    
            if(OrderOperateType.CREATE_ORDER.equals(operateType)) {
                operateContent = "完成订单创建,订单编号为:" + order.getOrderNo(); 
            } else if(OrderOperateType.CANCEL_ORDER.equals(operateType)) {
                operateContent = "取消订单,订单编号为:" + order.getOrderNo();
            } else if(OrderOperateType.PAY_ORDER.equals(operateType)) {
                operateContent = "支付订单,订单编号为:" + order.getOrderNo() + ",支付金额为:" + order.getPayableAmount();
            } else if(OrderOperateType.GOODS_DELIVERY.equals(operateType)) {
                operateContent = "已经将订单中的商品进行发货"; 
            } else if(OrderOperateType.CONFIRM_RECEIPT.equals(operateType)) {
                operateContent = "完成确认收货"; 
            } else if(OrderOperateType.APPLY_RETURN_GOODS.equals(operateType)) {
                operateContent = "申请退货"; 
            } else if(OrderOperateType.RETURN_GOODS_REJECTED.equals(operateType)) {
                operateContent = "退货申请审核不通过"; 
            } else if(OrderOperateType.RETURN_GOODS_APPROVED.equals(operateType)) {
                operateContent = "退货申请审核已通过"; 
            } else if(OrderOperateType.SEND_OUT_RETURN_GOODS.equals(operateType)) {
                operateContent = "寄送退货商品"; 
            } else if(OrderOperateType.CONFIRM_RETURN_GOODS_RECEIPT.equals(operateType)) {
                operateContent = "确认收到退货商品"; 
            } else if(OrderOperateType.FINISHED_RETURN_GOODS_INPUT.equals(operateType)) {
                operateContent = "完成退货商品入库"; 
            } else if(OrderOperateType.FINISHED_RETURN_GOODS_REFUND.equals(operateType)) {
                operateContent = "完成退款"; 
            }     
    
            OrderOperateLogDO log = create(order, operateType, operateContent);
            return log;
        }
    
        /**
         * 创建订单操作日志
         * @param operateType 订单操作类型
         * @param operateContent 订单操作内容
         * @return 订单操作日志
         * @throws Exception
         */
        private OrderOperateLogDO create(OrderInfoDTO order ,
                Integer operateType, String operateContent) throws Exception {
            OrderOperateLogDO log = new OrderOperateLogDO();
    
            log.setOrderInfoId(order.getId()); 
            log.setOperateType(operateType);
            log.setOperateContent(operateContent); 
            log.setGmtCreate(new Date());
            log.setGmtModified(new Date()); 
            return log;
        }
    
    }
  4. 订单状态流转

    我们只列出来订单create和cacel两种状态,因为状态流转时要判断当前状态是否可以流转到下一个状态,所以这里还有一个canCancel方法。

    /**
     * 订单状态管理器接口
     * @author wangmeng
     *
     */
    interface OrderStateManager {
    
        /**
         * 创建订单
         * @param order 订单
         * @throws Exception
         */
        void create(OrderInfoDTO order) throws Exception;
    
        /**
         * 订单能否执行取消操作
         * @param order 订单
         * @return 能否执行取消操作
         * @throws Exception
         */
        Boolean canCancel(OrderInfoDTO order) throws Exception;
    
        /**
         * 执行取消订单操作
         * @param order 订单
         * @throws Exception
         */
        void cancel(OrderInfoDTO order) throws Exception;
    
        // 这里还会有更多的订单状态:支付、确认收货、发货、退货等等状态流转
    }
  5. OrderStateManager实现类

    /**
     * 订单状态管理器
     * @author wangmeng
     *
     */
    @Component
    public class OrderStateManagerImpl implements OrderStateManager {
    
        /**
         * 已取消状态
         */
        @Autowired
        private CanceledOrderState canceledOrderState;
    
        /**
         * 待付款状态
         */
        @Autowired
        private WaitForPayOrderState waitForPayOrderState;
    
        /**
         * 创建订单
         * @param order 订单
         * @throws Exception
         */
        @Override
        public void create(OrderInfoDTO order) throws Exception {
            waitForPayOrderState.doTransition(order);
        }
    
        /**
         * 订单能否执行取消操作
         * @param order 订单
         * @return 能否执行取消操作
         * @throws Exception
         */
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return getOrderState(order).canCancel(order);
        }
    
        /**
         * 执行取消订单操作
         * @param order 订单
         * @throws Exception
         */
        @Override
        public void cancel(OrderInfoDTO order) throws Exception {
            canceledOrderState.doTransition(order); 
        }
    
        /**
         * 获取订单状态组件
         * @param order 订单
         * @return 订单状态组件
         * @throws Exception
         */
        private OrderState getOrderState(OrderInfoDTO order) throws Exception {
            if(OrderStatus.WAIT_FOR_PAY.equals(order.getOrderStatus())) {
                return waitForPayOrderState;
            } else if(OrderStatus.CANCELED.equals(order.getOrderStatus())) {
                return canceledOrderState;
            } else if(OrderStatus.WAIT_FOR_DELIVERY.equals(order.getOrderStatus())) {
                return waitForDeliveryOrderState;
            } else if(OrderStatus.WAIT_FOR_RECEIVE.equals(order.getOrderStatus())) {
                return waitForReceiveOrderState;
            } else if(OrderStatus.FINISHED.equals(order.getOrderStatus())) {
                return finishedOrderState;
            } else if(OrderStatus.WAIT_FOR_RETURN_GOODS_APPROVE.equals(order.getOrderStatus())) {
                return waitForReturnGoodsApproveOrderState;
            }
            return defaultOrderState;
        }
    }

    OrderState:

    /**
     * 订单状态
     * @author wangmeng
     *
     */
    public interface OrderState {
    
        /**
         * 订单流转到当前这个状态
         * @param order 订单
         * @throws Exception
         */
        void doTransition(OrderInfoDTO order) throws Exception;
    
        /**
         * 判断当前状态下能否执行取消订单操作
         * @param order 订单
         * @return 能否执行取消订单操作
         * @throws Exception
         */
        Boolean canCancel(OrderInfoDTO order) throws Exception;
    }

    WaitForPayOrderState:

    /**
     * 待付款状态
     * @author wangmeng
     *
     */
    @Component
    public class WaitForPayOrderState extends AbstractOrderState {
    
        @Autowired
        public WaitForPayOrderState(DateProvider dateProvider, OrderInfoDAO orderInfoDAO) {
            super(dateProvider, orderInfoDAO);
        }
    
        @Override
        protected Integer getOrderStatus(OrderInfoDTO order) throws Exception {
            return OrderStatus.WAIT_FOR_PAY;
        }
    
        @Override
        public Boolean canPay(OrderInfoDTO order) throws Exception {
            return true;
        }
    
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return true;
        }
    }

    AbstractOrderState:

    /**
     * 订单状态的抽象基类
     * @author wangmeng
     *
     */
    public abstract class AbstractOrderState implements OrderState {
    
        /**
         * 订单管理DAO组件
         */
        protected OrderInfoDAO orderInfoDAO;
    
        public AbstractOrderState(OrderInfoDAO orderInfoDAO) {
            this.orderInfoDAO = orderInfoDAO;
        }
    
        /**
         * 订单流转到当前这个状态
         * @param order 订单
         */
        @Override
        public void doTransition(OrderInfoDTO order) throws Exception {
            Integer orderStatus = getOrderStatus(order);
            order.setOrderStatus(orderStatus);
            orderInfoDAO.updateStatus(order.getId(), orderStatus);  
        }
    
        /**
         * 获取订单状态
         * @param order 订单
         * @return 订单状态
         * @throws Exception
         */
        protected abstract Integer getOrderStatus(OrderInfoDTO order) throws Exception;
    
        /**
         * 判断当前状态下能否执行取消订单操作
         * @param order 订单
         * @return 能否执行取消订单操作
         */
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return false;
        }
    }

总结

上面只是讲了 订单中心提交订单中使用了 状态模式简单工厂模式装饰器模式

状态模式:OrderStat + OrderStateManager等

简单工厂模式:OrderOperateLogFactory

装饰器模式:LoggedOrderStateMananger

其中LoggedOrderStateMananger实现了OrderStateManager接口,增强了create、cancel、pay等方法的实现,添加了记录日志的功能,使得状态流转后 可以自动记录日志的功能。

这里只是将精简后的代码提供出来,我相信认真看一下还是很易懂的,后面还有提交订单 后面的一些流程,会单独在开一片文章来讲解,敬请期待。

申明

本文章首发自本人博客: https://www.cnblogs.com/wang-meng 和公众号: 壹枝花算不算浪漫 ,如若转载请标明来源!

感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫

eMfmmeZ.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK