一、裝飾者模式 1、裝飾者模式(Decorator Pattern):指在不改變原有對象的基礎之上,將功能附加到對象上,提供了比繼承更有彈性的替代方案(擴展原有對象的功能)。(屬於結構型模式) 2、適用場景 用於擴展一個類的功能或給一個類增加附加職責 動態的給一個對象添加功能,這些功能可以再動態的撤 ...
一、裝飾者模式
1、裝飾者模式(Decorator Pattern):指在不改變原有對象的基礎之上,將功能附加到對象上,提供了比繼承更有彈性的替代方案(擴展原有對象的功能)。(屬於結構型模式)
2、適用場景
- 用於擴展一個類的功能或給一個類增加附加職責
- 動態的給一個對象添加功能,這些功能可以再動態的撤銷
3、優點
- 裝飾者是繼承的有力補充,比繼承靈活,不改變原有對象的情況下動態地給一個對象擴展功能,即插即用
- 通過使用不同裝飾類以及這些裝飾類的排列組合,可以實現不同效果
- 裝飾者完全遵循開閉原則
4、缺點
- 會出現更多的代碼、更多的類,增加程式複雜性
- 動態裝飾時,多層裝飾時會更複雜
5、應用場景舉例
例子1:早上買個煎餅去公司吃,賣煎餅的大姐可以給你的煎餅加雞蛋、也可以加熱狗等。
定義一個煎餅Cake類:
定義一個加雞蛋的煎餅CakeWithEgg類:
再定義一個既加雞蛋又加熱狗的煎餅CakeWithEggAndHotdog類:
客戶端測試代碼:
運行結果:
類結構圖:
運行結果沒有問題。但如果用戶需要一個加2個雞蛋、加1根熱狗的煎餅,那麼用現在的類結構是創建不出來的,也無法自動計算出價格,除非再創建一個類做定製,如果需求再變,一直加定製顯然是不科學的。下麵用裝飾者模式來解決上面的問題。
首先定義一個製作煎餅的抽象類Cake:
定義一個基本的煎餅(基礎套餐)BaseCake類:
定義一個擴展套餐的抽象裝飾者CakeDecorator類:
定義一個雞蛋裝飾者EggDecorator類:
定義一個熱狗裝飾者HotdogDecorator類:
客戶端測試代碼:
運行結果:
類結構圖:
例子2:上次講的適配器模式,為了實現新功能與老功能相容,定義一個新的類繼承已有的類來實現功能擴展,遵循開閉原則。今天再用裝飾者模式再升級一次代碼,同時也做一個更好的對比。
先看原來的代碼,User類:
Result類:
ISignInService介面:
SignInServiceImpl實現類:
來看升級以後的代碼,定義一個新的介面ISignInForThirdService繼承原來的介面:
定義一個新的邏輯處理類SignInForThirdServiceImpl,實現第三方登錄自由適配:
客戶端測試代碼:
裝飾者模式最本質的特征是將原有類的附加功能抽離出來,簡化原有類的邏輯。其實抽象的裝飾者是可有可無的,具體可以根據業務模型來選擇。
6、裝飾者模式和適配器模式的對比
裝飾者和適配器模式都是包裝模式(Wrapper Pattern),裝飾者也是一種特殊的代理模式。
7、裝飾者模式在源碼中的應用
① 在JDK中體現最明顯的類就是IO相關的類,如BufferedReader、InputStream、OutputStream,看一下常用的InputStream類結構圖:
② 在Spring中的TransactionAwareCacheDecorator類也有用到,該類主要是用來處理事務緩存相關,如下代碼:
③ TransactionAwareCacheDecorator就是對Cache的一個包裝。再如MVC中的裝飾者模式HttpHeadResponseDecorator類:
二、觀察者模式
1、觀察者模式(Observer Pattern):指定義了對象之間的一對多依賴,讓多個觀察者對象同時監聽一個主體對象,當主體對象發生變化時,它的所有依賴者(觀察者)都會收到通知並更新。(屬於行為型模式,觀察者模式有時也叫做發佈訂閱模式)
2、優點
- 觀察者和被觀察者之間建立了一個抽象的耦合
- 觀察者模式支持廣播通信
3、缺點
- 觀察者之間有過多的細節依賴、提高時間消耗及程式的複雜度
- 使用要得當,要避免迴圈調用
4、應用場景舉例
觀察者模式主要用於在關聯行為之間建立一套觸發機制的場景。比如微信朋友圈動態通知、群消息通知、郵件通知、廣播通知、桌面程式的事件響應等。如下:
例子:生產者與消費者模型。使用JDK提供的一種觀察者的實現方式來實現。
先定義一個消息Message類:
定義一個生產者Productor類:
定義一個消費者Consumer類:
客戶端測試代碼:
運行結果:
5、基於Guava API輕鬆落地觀察者模式
先引入Guava框架的Maven依賴包:
定義一個監聽事件GuavaEvent類:
客戶端測試代碼:
運行結果: