以前在個人博客(一枝花算不算浪漫)中已經更新過兩篇設計模式相關的內容html
上面內容都是基於真實業務場景精簡後的設計(工做中真實場景使用到的)。java
以前爲了學習設計模式,看過網上不少相關博客講解,大都是畫下UML類圖,舉例幾個絕不相干的demo,看了幾遍仍然是雲裏霧裏。數據庫
由於本身如今作的項目就是屬於B2C的商城,項目中使用到了大量的設計模式,因此這裏精簡真實的業務場景,將核心的業務代碼抽離出來。代碼不涉及任何公司信息,全部敏感信息都已屏蔽,代碼只用做學習交流使用。設計模式
一圖流,首先看下提交訂單 咱們抽象出的一些場景:異步
訂單中心: 一、訂單中心建立訂單 二、訂單狀態流轉(狀態模式) 三、記錄操做日誌(裝飾器模式+簡單工廠模式) 四、訂單中心通知 庫存中心更新庫存ide
調度中心: 一、庫存中心更新本地庫存(使用命令模式+模板方法模式+工廠模式) 這個上講已經說過:【一塊兒學設計模式】命令模式+模板方法+工廠方法實戰: 如何優雅的更新商品庫存... 二、將更新庫存數據放到消息中,調度中心消費消息(中介模式) 三、放入消息隊列中,判斷隊列是否放滿了,若是放滿了須要創建離線存儲(備忘錄模式) 四、異步監聽消息處理結果(觀察者模式)學習
這個模型應該很簡單,咱們來一步步拆解 一步步代碼分析this
訂單中心提交訂單操做spa
/** * 訂單狀態管理器 */ @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; }
訂單狀態管理器設計
/** * 會自動記錄日誌的訂單狀態管理器 * @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)); } }
日誌操做工廠
/** * 訂單操做內容工廠 * @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; } }
訂單狀態流轉 咱們只列出來訂單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; // 這裏還會有更多的訂單狀態:支付、確認收貨、發貨、退貨等等狀態流轉 }
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 和公衆號:壹枝花算不算浪漫,如若轉載請標明來源!
感興趣的小夥伴可關注我的公衆號:壹枝花算不算浪漫
原文出處:https://www.cnblogs.com/wang-meng/p/12038619.html