日常咱們在工做開發過程當中,每每由於工期問題致使總體功能設計考慮的不夠周到,致使後期迭代時發現須要原有功能流程基礎上追加新功能時,須要耗費更多的成本,沒法輕易推翻重構,接着即是將錯就錯,在if else之下再來一層elseif。因此好代碼結構,每每時項目經驗積累出來的,會了不表明能,只有實踐了、實現了,有實際價值體現了,才能發現學習是一點點積累進步的過程。設計模式
而設計模式自己就是經過無數項目積累沉澱而來,適合什麼方式什麼方案去設計實現功能,每每須要全局的分析,考慮到總體,以及將來的可擴展性等等。ide
工做中其實有不少功能是可使用設計模式的,經過設計模式去優化代碼,達到代碼的複用性,減小耦合,也就是咱們常說的高內聚低耦合。學習
事情是這樣的,小陳接到領導的工做分配,告知要爲負責的商城項目實現下單功能,因而小陳是成竹在胸的實現了,因爲時間問題,小陳並無對功能花時間去作過多設計。便有了如下代碼:優化
@Override @Transactional(rollbackFor = ServiceException.class) public String createBuyOrders(BuyOrders buyOrders, List<String> couponIds, Long integral, Long integralGym)throws ServiceException{ productBll.updateSkuStockAndSaleNumber(buyOrders.getBuyOrderProductId(), buyOrders.getBuyOrderSkuId(), buyOrders.getBuyOrderQuantity()); //訂單基礎信息 creatOrderBase(buyOrders); //計算訂單價格 normalCalculationOrderPrice(buyOrders); //完善地址信息 setOrderAddress(buyOrders); //調用優惠券 couponBll.useCoupons(buyOrders.getBuyOrderUserId(),buyOrders,couponIds); if(!IIntegralInfoBll.buyUseIngegral(buyOrders, integral, integralGym)){ throw new ServiceException("積分扣除失敗,請從新下單"); } if (FavoritesHelper.isNotNull(IBuyOrdersDao.insertBuyOrders(buyOrders))){ //建立訂單關閉訂單任務 if (FavoritesHelper.isNotEmpty(systemVariable)){ closeTime = systemVariable.getSystemVariableVale(); } quartzService.orderTimeout(buyOrders.getBuyOrderNo(),ISystemVariableBll.ORDER_TIME_OVER); return buyOrders.getBuyOrderNo(); } throw new RuntimeExcaption("訂單建立失敗"); 過了幾周甲方提出了需求,想要實現拼多多那種團購功能,可是由於有優惠了,因此部分優惠券沒法使用。小陳以爲沒什麼壓力,因而對新增了一種訂單類型:團購訂單: public String createBuyOrders(BuyOrders buyOrders, List<String> couponIds, Long integral, Long integralGym)throws ServiceException{ if(buyOrders.getType == 1){ //正常訂單;參考上一段代碼 } else if( buyOrders.getType == 2 ){ //團購訂單;具體功能腦部 //大概實現點:知足設置多少人成爲一個團,參加多久人沒齊會自動取消,拼團過程當中有人退出處理,成功處理,訂單生成未支付鎖定處理 } else{ throw new RuntimeException("錯誤的訂單類型"); } }
至此,小陳以爲沒啥壓力,也就一個方法幾百行代碼,小問題。debug
又過了幾周,甲方新需求,要有一個秒殺和商品預售功能,小陳頓感壓力,仍是硬着頭皮上了,不就是多幾個if else嗎,還就沒有我小陳ifelseif實現不了的功能了,若是有,就再來一次 else if。設計
因而乎...:指針
public String createBuyOrders(BuyOrders buyOrders, List<String> couponIds, Long integral, Long integralGym)throws ServiceException{ if(buyOrders.getType == 1){ //正常訂單;參考上一段代碼 } else if( buyOrders.getType == 2 ){ //團購訂單;具體功能腦補 //大概實現點:知足設置多少人成爲一個團,參加多久人沒齊會自動取消,拼團過程當中有人退出處理,成功處理,訂單生成未支付鎖定處理 } else if( buyOrders.getType == 3 ){ //秒殺訂單;具體功能腦補 //大概實現點:知足條件商品進行秒殺搶購,流量消峯、庫存控制、訂單生成 } else if( buyOrders.getType == 4 ){ //商品預售訂單;具體功能腦補 //大概實現點:訂價膨脹,尾款支付提醒 } else{ throw new RuntimeException("錯誤的訂單類型"); } }
沒等小陳接到甲方的下一個需求,小陳因爲多是我的緣由辭職了,因而新來的阿彬接受了小陳的代碼,碰巧甲方來了新需求:我想來個週期購,增長我商城的復購率...balabala...code
因而阿彬打開先輩的代碼一看,好傢伙,絕了!這東西我怎麼...尚未註釋...orm
其實向上述的業務情形還有不少,好比與其相對於的商品新增。例如商品填寫完基礎信息以後須要知足商品的週期購售賣邏輯,須要相對於的商品配置邏輯;相對的團購也是,預售商品更爲複雜。咱們能夠一開始就對這些功能進行合理的規劃,而後找出了優化(簡化)的點。就算優化不了,也可將總體的代碼進行合理的設計,不至於維護起來花費太多的成本。對象
下單從新實現:
//1首先:定義下單接口 public interface ICreateOrderBll { void createOrder(BuyOrders orders); } //2其次:實現下單接口 //2.1秒殺 public class KillSaleOrderBllImpl implements ICreateOrderBll { @Override public void createOrder(BuyOrders orders) { } } //2.2普通訂單 public class NormalOrderBllImpl implements ICreateOrderBll { @Override public void createOrder(BuyOrders orders) { } } //3預售訂單 public class PreSaleOrderBllImpl implements ICreateOrderBll { @Override public void createOrder(BuyOrders orders) { } } //4團購訂單 public class GroupSaleOrderBllImpl implements ICreateOrderBll { @Override public void createOrder(BuyOrders orders) { } } //5建立工廠方法的工廠 public class BuyOrderFactory { public ICreateOrderBll getOrderBll(OrderTypeEnum orderType) throws RuntimeException{ if (ObjectHelper.isEmpty(orderType)) return null; else if (orderType.equals(OrderTypeEnum.NORMAL_ORDER)) return new NormalOrderBllImpl(); else if (orderType.equals(OrderTypeEnum.KILL_SALE)) return new KillSaleOrderBllImpl(); else if (orderType.equals(OrderTypeEnum.PRE_SALE)) return new PreSaleOrderBllImpl(); else if (orderType.equals(OrderTypeEnum.GROUP_SALE)) return new GroupSaleOrderBllImpl(); else throw new RuntimeException("不存在的訂單類型"); } } //6備註:其中OrderTypeEnum 是定義的訂單類型枚舉類 //7調用 public void createNewOrder(){ BuyOrders killSaleOrder = new BuyOrders(); BuyOrderFactory factory = new BuyOrderFactory(); ICreateOrderBll killSaleService = factory.getOrderBll(OrderTypeEnum.KILL_SALE); killSaleService.createOrder(killSaleOrder);//秒殺業務 BuyOrders preSaleOrder = new BuyOrders(); ICreateOrderBll preSaleService = factory.getOrderBll(OrderTypeEnum.PRE_SALE); preSaleService.createOrder(preSaleOrder);//預售 }
自此,下單就重構完成(具體實現根據要求來)。
小陳經過學習瞭解了工廠方法,懂得了其中的些許奧祕,但是奈何項目是SpringBoot,只學了皮毛的小陳照虎畫貓,去發現實現的代碼,在代碼執行到具體的業務實現層卻發現空指針,不對啊,不是傳進來的對象都有收到啊,怎麼沒會空指針呢,商品也正常獲取啊,怎麼回事呢?
經過debug,小陳發現是所寫的代碼沒有成功注入SpringBoot中,是對象直接報空指針,因此調用方法是拋出了異常。
因而,小陳悟了:
//重點圈圈1 @Component public class BuyOrderFactory { //重點圈圈2 @Resource private Map<OrderTypeEnum,ICreateOrderBll> handlerMap; public ICreateOrderBll getOrderBll(OrderTypeEnum orderType) throws RuntimeException{ if (ObjectHelper.isEmpty(orderType)) return null; else if (orderType.equals(OrderTypeEnum.NORMAL_ORDER)) return new NormalOrderBllImpl(); else if (orderType.equals(OrderTypeEnum.KILL_SALE)) return new KillSaleOrderBllImpl(); else if (orderType.equals(OrderTypeEnum.PRE_SALE)) return new PreSaleOrderBllImpl(); else if (orderType.equals(OrderTypeEnum.GROUP_SALE)) return new GroupSaleOrderBllImpl(); else throw new RuntimeException("不存在的訂單類型"); } } //調用 //重點圈圈3 @Resource BuyOrderFactory factory; public void createNewOrder(){ BuyOrders killSaleOrder = new BuyOrders(); ICreateOrderBll killSaleService = factory.getOrderBll(OrderTypeEnum.KILL_SALE); killSaleService.createOrder(killSaleOrder);//秒殺業務 BuyOrders preSaleOrder = new BuyOrders(); ICreateOrderBll preSaleService = factory.getOrderBll(OrderTypeEnum.PRE_SALE); preSaleService.createOrder(preSaleOrder);//預售 }
再後來,小陳由此開始了設計模式學習的不歸路。