【一起學設計模式】狀態模式+裝飾器模式+簡單工廠模式實戰:(一)提交個訂單我到底經歷了什麼鬼?...

前言

之前在我的博客(一枝花算不算浪漫)中已經更新過兩篇設計模式相關的內容

上面內容都是基於真實業務場景精簡後的設計(工作中真實場景使用到的)。

之前爲了學習設計模式,看過網上很多相關博客講解,大都是畫下UML類圖,舉例幾個毫不相干的demo,看了幾遍仍然是雲裏霧裏。

因爲自己現在做的項目就是屬於B2C的商城,項目中使用到了大量的設計模式,所以這裏精簡真實的業務場景,將核心的業務代碼抽離出來。代碼不涉及任何公司信息,所有敏感信息都已屏蔽,代碼只用作學習交流使用。

業務場景

一圖流,首先看下提交訂單 我們抽象出的一些場景:

17C4F70C-E159-4AD8-B394-232A54F52F01.png

訂單中心:
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 和公衆號:壹枝花算不算浪漫,如若轉載請標明來源!

感興趣的小夥伴可關注個人公衆號:壹枝花算不算浪漫

22.jpg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章