裝飾者設計模式:
簡單定義:加強一個類的功能,並且還可讓這些裝飾類互相裝飾。設計模式
應用場景:當要在某個功能的基礎上擴充功能,而且擴充的功能具備大量排列組合,經過繼承關係會衍生出大量子類,這時候用裝飾者模式來解決。ide
裝飾者設計模式的步驟:
1. 在裝飾類的內部維護一個被裝飾類的引用。
2. 讓裝飾類有一個共同的父類或者是父接口。ui
例如:人有一種行爲叫「吃水果」,其中水果有4種:蘋果、香蕉、鴨梨、橘子
如今有需求以下:
A類人行爲:吃蘋果
B類人行爲:先吃蘋果,再吃香蕉
C類人行爲:先吃香蕉,再吃蘋果
D類人行爲:先吃橘子,後吃鴨梨this
咱們先用子類繼承來實現:代碼以下spa
1 interface IEatFruit{ 2 public void eatFruit(); 3 } 4 5 class PersonA implements IEatFruit{ 6 7 @Override 8 public void eatFruit() { 9 System.out.println("吃蘋果"); 10 } 11 12 } 13 class PersonB implements IEatFruit{ 14 15 @Override 16 public void eatFruit() { 17 System.out.println("吃蘋果"); 18 System.out.println("吃香蕉"); 19 } 20 21 } 22 class PersonC implements IEatFruit{ 23 24 @Override 25 public void eatFruit() { 26 System.out.println("吃香蕉"); 27 System.out.println("吃蘋果"); 28 } 29 30 } 31 class PersonD implements IEatFruit{ 32 33 @Override 34 public void eatFruit() { 35 System.out.println("吃橘子"); 36 System.out.println("吃鴨梨"); 37 } 38 39 }
這樣固然是沒問題的,每一類人對應new出來的對象 均可以實現對應的需求。
可是,當需求改成:
某類人行爲:吃上面四種水果,而且要求有前後順序
這樣的排列組合有24種....
這樣你還會用繼承去作嗎?寫24個子類去實現接口,明顯不合適。
這時候若是用到裝飾者模式,代碼則會變成:設計
1 interface IEatFruit{ 2 public void eatFruit(); 3 } 4 5 class PersonA implements IEatFruit{ 6 IEatFruit eat; 7 public PersonA(){ 8 this.eat = this; 9 } 10 public PersonA(IEatFruit _eat){ 11 this.eat = _eat; 12 } 13 @Override 14 public void eatFruit() { 15 if(!(this.eat instanceof PersonA)){ 16 this.eat.eatFruit(); 17 System.out.println("吃蘋果"); 18 }else{ 19 System.out.println("吃蘋果"); 20 } 21 } 22 23 } 24 class PersonB implements IEatFruit{ 25 IEatFruit eat; 26 public PersonB(){ 27 this.eat = this; 28 } 29 public PersonB(IEatFruit _eat){ 30 this.eat = _eat; 31 } 32 @Override 33 public void eatFruit() { 34 if(!(this.eat instanceof PersonB)){ 35 this.eat.eatFruit(); 36 System.out.println("吃香蕉"); 37 }else{ 38 System.out.println("吃香蕉"); 39 } 40 } 41 42 } 43 class PersonC implements IEatFruit{ 44 IEatFruit eat; 45 public PersonC(){ 46 this.eat = this; 47 } 48 public PersonC(IEatFruit _eat){ 49 this.eat = _eat; 50 } 51 @Override 52 public void eatFruit() { 53 if(!(this.eat instanceof PersonC)){ 54 this.eat.eatFruit(); 55 System.out.println("吃鴨梨"); 56 }else{ 57 System.out.println("吃鴨梨"); 58 } 59 } 60 61 } 62 class PersonD implements IEatFruit{ 63 IEatFruit eat; 64 public PersonD(){ 65 this.eat = this; 66 } 67 public PersonD(IEatFruit _eat){ 68 this.eat = _eat; 69 } 70 @Override 71 public void eatFruit() { 72 if(!(this.eat instanceof PersonD)){ 73 this.eat.eatFruit(); 74 System.out.println("吃橘子"); 75 }else{ 76 System.out.println("吃橘子"); 77 } 78 } 79 80 } 81 82 83 84 public class Demo2 { 85 86 public static void main(String[] args) { 87 //這樣就能夠經過上述4類人來相互裝飾,就能夠隨意任意一種組合「吃水果」 88 //如:吃橘子->吃蘋果 89 PersonD d = new PersonD(); 90 PersonA a = new PersonA(d); 91 a.eatFruit(); 92 System.out.println("-------我是分割線------------"); 93 //如:吃蘋果->吃橘子->吃鴨梨->吃香蕉 94 PersonA a2 = new PersonA(); 95 PersonD d2 = new PersonD(a2); 96 PersonC c2 = new PersonC(d2); 97 PersonB b2 = new PersonB(c2); 98 b2.eatFruit(); 99 } 100 101 }
輸出結果以下:
吃橘子
吃蘋果
-------我是分割線------------
吃蘋果
吃橘子
吃鴨梨
吃香蕉code
最後總結:
繼承實現的加強類和修飾模式實現的加強類有何區別?
繼承實現的加強類:
優勢:代碼結構清晰,並且實現簡單.
缺點:對於每個的須要加強的類都要建立具體的子類來幫助其加強,這樣會致使
繼承體系過於龐大。
裝飾者模式實現的加強類:
優勢:內部能夠經過多態技術對多個須要加強的類進行加強, 可使這些裝飾類
達到互相裝飾的效果。使用比較靈活。
缺點:須要內部經過多態維護須要被加強的類的實例。進而使得代碼稍微複雜對象