外观模式coding
生活随笔
收集整理的這篇文章主要介紹了
外观模式coding
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
外觀模式也叫門模式,這個模式非常簡單,也容易理解,我們先創建結構性模式的一個包,還記得我們之前學過迪米特法則嗎,也叫最少知道法則,你外觀模式是迪米特法則非常好的典型例子,降低我們應用層與子系統類之間的耦合度,那現在我們引入一個業務場景,就那網站來說,網站是提供一個積分禮物這么一個功能的,比如這里面有很多禮物,然后每個禮物兌換所要的積分都不一樣,然后我們個人是持有一定積分的,例如我先做只有1668個,那么禮物兌換的時候我們想象一下,這里面都有哪些子系統呢,首先禮物的庫存校驗是要有的,還有積分校驗,當前這個積分是否滿足這個禮物要求的積分數量呢,還有一個積分支付這么一個子系統,還要有對接物流系統,對禮物進行配送,那剛剛說的簡單來說,資格校驗,積分支付,還有物流系統對接,這三個都可以理解成子系統,無論成功失敗,我們都可以封裝一個禮物外觀類,把這些邏輯封裝起來,那具體體會呢,我們一邊coding一邊來體會,回到代碼中,首先我們要創建一個禮物,PointGift
把這些關系都打開,然后最大化一下再放大,為了看得更清楚,這個Gift放到邊上,首先對外會提供一個giftExchange方法,下面有三個子系統,分別是資格校驗,物流,還有積分支付,對這個關系一比一,也就是一個禮物兌換的服務,包含資格服務,物流服務子系統,還有積分支付子系統,他們之間是組合關系,對外部我們只和外觀類通訊,所有的子系統應用層,是不需要關心的,這個圖很好的詮釋了模式的UML基本類圖,那現在我們來寫一個Test
首先Test是應用層,這個是禮物的實體類,把子系統要放到下邊,我們來看一下,這個UML類圖,前面我們有強調,應用層是不需要關心子系統的,但是這里面我們埋了一個伏筆,這個伏筆是什么呢,看我們的這個圖,Test關心的子系統,create這么一條線,這三條線,那實際我們在使用的時候,只要保證Test和外觀類這條線是OK的,但是這里面為什么還有線呢,很簡單,我們看一下,Test這里面的實現
來關心了這些子系統的類,創建了子系統的對象了,注入到外觀對象里邊,那是因為我們沒有集成Spring,那現在呢,我們就模擬一下,假設在外觀類初始化的時候,這些service是創建好的,所以我們直接在這里面new一個我們再來看一下UML類圖,可以看到Test應用層,到3個子系統的先已經消失了,這種UML類圖,才是標準的外觀模式,也就是應用層不需要關注子系統,子系統只和外觀類通訊,應用層只和外觀類通信,具體理念,外觀校驗的邏輯,物流的邏輯,還有積分支付的邏輯,Test應用層,全部不需要關心,所以我們日常在開發工作的時候,要注意我們的應用層到底有沒有和子系統發生關系,這個也是檢驗外觀模式使用正確與否的一個因數,那這里面我們注意一下,我們這個外觀類使用的是實體外觀類,那從UML類圖當中可以看出來,他非常完美的支持了迪米特法則,但是我們右側一個黑框,右新增了一個子系統了,我們還要修改這個實體外觀類,那從這個角度來分析,他呢并不符合開閉原則,那再擴展一下,如果我們這個外觀類我們使用抽象外觀類的話,也就是外面有一個接口外觀類,通過這個實體外觀類,實現上邊的接口,這個就是擴展的方式,但是我們具體是使用實體外觀類,還是通過抽象外觀類,來實現業務場景呢,還是要看具體的業務場景要求,包括對他擴展性的一個預期,如果這個外觀類不需要經常變化,或者以后的擴展非常有限的話,那我們直接使用實體外觀類也是OK的,可以減少復雜度,如果預期到每兩周就要新增一個子系統,那我們就要使用抽象外觀類了,例如說我們有一個抽象外觀類,giftExchangeService,在寫一個實現這個抽象外觀類的實體類,然后如果里面邏輯變化比較大的話,在通過應用層,使用新的實體外觀類,這樣老的就不需要變化的,甚至對于版本控制,我們在實際業務場景當中,經常有說一個APP有不同的版本,可能你現在的邏輯是不一樣的,在版本控制上,也可以找到適合的場景,打個比方,我們可以通過手機具體使用某個APP的版本號,然后我們聲明很多版本的外觀類,1.0版本的外觀,1.1版本的外觀,1.2版本的外觀類,然后通過不同版本,來調用不同的外觀類實現,也是OK的,外觀模式也是非常簡單的設計模式,但是剛剛也強調了,一定要注意應用層,不要和子系統發生交互,這些線一定要干掉,他只和外觀類發生交互,就OK了,這個一定要理解透,希望通過這個外觀模式的學習,能把這個模式理解好,掌握好
package com.learn.design.pattern.structural.facade;/*** * @author Leon.Sun**/
public class PointsGift {/*** 我們只聲明一個name* 我們還可以聲明里面的庫存* * */private String name;/*** 然后通過構造器來定義積分禮物* * @param name*/public PointsGift(String name) {this.name = name;}/*** 開放禮物的getName* * * @return*/public String getName() {return name;}
}
package com.learn.design.pattern.structural.facade;/*** 這個子系統叫做QualifyService* 這里面的實現也很簡單* * * @author Leon.Sun**/
public class QualifyService {/*** 首先肯定會返回一個布爾* 方法名就叫isAvailable* 就是對應的禮物是否有資格* * 實際的業務是需要寫大量的業務邏輯* 資格校驗完成之后呢* 就是積分支付的一個子系統* * * @param pointsGift* @return*/public boolean isAvailable(PointsGift pointsGift){/*** 校驗禮物的名字* 禮物的名字打上了* 積分資格通過* 庫存通過* */System.out.println("校驗"+pointsGift.getName()+" 積分資格通過,庫存通過");/*** 直接return true* 這個邏輯就寫完了* * */return true;}
}
package com.learn.design.pattern.structural.facade;/*** * @author Leon.Sun**/
public class PointsPaymentService {/*** 也是返回布爾* 返回值積分是否成功* 把禮物傳進來* 這里面可能就要用到禮物所需要的積分數量* 和個人所有的積分數量業務邏輯對比* * * @param pointsGift* @return*/public boolean pay(PointsGift pointsGift){//扣減積分/*** 各種扣減積分的邏輯* 直接支付* 拿到這個name* 支付哪個禮物的* 積分成功* * */System.out.println("支付"+pointsGift.getName()+" 積分成功");/*** 直接return true* 這個邏輯也比較簡單* */return true;}}
package com.learn.design.pattern.structural.facade;/*** 物流子系統* 物流相關的子系統* * * @author Leon.Sun**/
public class ShippingService {/*** 我們直接返回String類型* 物流系統完成之后* 返回物流訂單號* shipGift運送禮物* Gift要傳進來* * * @param pointsGift* @return*/public String shipGift(PointsGift pointsGift){/*** 輸出一下物流系統的對接邏輯* 然后輸出進入物流系統* 什么進入物流系統呢* 當然是這個禮物* * */System.out.println(pointsGift.getName()+"進入物流系統");/*** 物流訂單號* * */String shippingOrderNo = "666";/*** 直接返回* 返回物流訂單號* 實際的訂單號肯定是物流系統之后* 有系統返回的物流訂單號* 那現在這三個子系統都寫完了* 我們應用層在對接的時候* 我要關注這三個子系統* 要挨個的進行交互* 首先交互資格* 然后扣減積分* 還要調用物流系統的積分禮物* 例如說我們這個禮物* 拆分之后* RPC服務* 對外提供這三個接口* 要求對接著來實現這三個服務* 同時還要保證他們的順序* 包括怎么使用* 那其實對方只關心一個禮物兌換邏輯* 那禮物兌換邏輯* 完全可以封裝到我們內部* 提供一個外觀類* 完全不需要知道這么多子系統* 包括里面的順序* 子系統的邏輯* 所以我們想一下迪米特法則* 那外觀模式可以很好的體現* 迪米特法則* 不該知道的就不知道* 那我們現在想要應用層知道什么呢* 很簡單* * * * */return shippingOrderNo;}
}
package com.learn.design.pattern.structural.facade;/*** 也就是說這個service在創建的時候* 里面依賴的子系統service呢* 都已經創建好了* 然后Test里面也不需要關心子系統了* 我們來run一下* * @author Leon.Sun**/
public class GiftExchangeService {/*** 這里要注入Service* * */private QualifyService qualifyService = new QualifyService();/*** 然后PointsPaymentService* * */private PointsPaymentService pointsPaymentService = new PointsPaymentService();/*** 還有ShippingService* 該怎么注入呢* 因為我們沒有集成Spring框架* * */private ShippingService shippingService = new ShippingService();/*** 對外提供一個方法* giftExchange* PointsGift* * * @param pointsGift*/public void giftExchange(PointsGift pointsGift){/*** 里面的邏輯很簡單* 我們調用isAvailable方法* 積分要符合* 資格要符合* 那else里面我們就不寫了* 我們主要是還是聚焦在設計模式上* 那公國之后我們還有一層校驗* 積分扣減是否成功* * */if(qualifyService.isAvailable(pointsGift)){//資格校驗通過/*** 把這個禮物pointsGift傳進來* * */if(pointsPaymentService.pay(pointsGift)){//如果支付積分成功/*** 如果支付積分成功* 這個時候就可以返回物流訂單號了* shippingService.shipGift* * */String shippingOrderNo = shippingService.shipGift(pointsGift);/*** 物流系統下單成功* 訂單號是shippingOrderNo* 我們現在來看一下* UML類圖* * * */System.out.println("物流系統下單成功,訂單號是:"+shippingOrderNo);}}}
}
package com.learn.design.pattern.structural.facade;/*** * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 首先創建PointsGift* 禮物就是T恤* * */PointsGift pointsGift = new PointsGift("T恤");/*** 我們new一個GiftExchangeService* 這里面為什么new呢* 正常我們可以通過Spring注入進來* 我們并沒有集成Spring框架* 我們還是聚焦在設計模式上* 硬編碼來創建這個Gift* * */GiftExchangeService giftExchangeService = new GiftExchangeService();/*** 接下來要往里面注入了* 注入三個子系統的service* 把pointsGift這個禮物傳進來* 看一下結果* 結果已經出來了* 校驗t恤* 積分資格通過* 庫存通過* 支付t恤* 積分成功* t恤進入物流系統* 物流系統下單成功* 返回的訂單號是666* 我們看一下最新的UML類圖* 因為新加了類* 所以要刷新一下* * */giftExchangeService.giftExchange(pointsGift);}
}
?
總結
以上是生活随笔為你收集整理的外观模式coding的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外观模式讲解
- 下一篇: 外观模式源码解析(springjdbc+