設計模式 (十)裝飾模式(Decorator)

Mindy_Lou發表於2017-06-23

裝飾模式(Decorator)就是使用被裝飾的一個子類的例項,在客戶端將這個子類的例項委託給裝飾類。裝飾模式是結成關係的一個替代方案。

簡單的裝飾模式是原理圖入下:


裝飾模式以對客服端透明的方式增添了物件的功能,其在與動態的給物件新增了責任,當然這裡的繼承便是靜態的。

其中重要的地方時裝飾物件和真是物件有相同的介面,這樣客戶端就可以和真是物件一樣的互動方式和裝飾物件互動,然後裝飾物件把所有從客戶端接收過來的請求全部轉發給真是物件,然後在返還給客戶端,這樣裝飾物件就可以再轉發前或者以後新增一些附加功能而不影響對真是物件的操作,這樣在不改變原有類的基礎想,可以實現對於原有類的這種額外功能的實現,增強了程式的複用性。

同時裝飾模式比繼承好的地方就是,裝飾模式可以動態的對已經存在的類進行任意的組合,實現想要的功能,而繼承是靜態的實現,不能改變原有類的實現,如果要新增更多的功能,只有新增更多的派生類來實現,這個簡潔在下面的例子裡對於最後一次列印輸出就有很明顯的效果,定義好了兩個裝飾類以後,不用再定義第三個就可以實現兩個裝飾類排列組合的效果。下面就簡單的做了一個通過對於手機接電話的一個擴充套件,接聽電話之前有一個彩鈴,接受電話之後會回撥一段廣告,這樣就出來了下面的例子:


[java] view plain copy
  1. package com.designpattern.decorator;  
  2.   
  3. public interface Phone {  
  4.     public void recevieCall(String name);  
  5. }  

[java] view plain copy
  1. package com.designpattern.decorator;  
  2.   
  3. public class ChinaMobile implements Phone {  
  4.   
  5.     @Override  
  6.     public void recevieCall(String name) {  
  7.         System.out.println("step recevie " + name + " call");  
  8.     }  
  9.   
  10. }  

[java] view plain copy
  1. package com.designpattern.decorator;  
  2.   
  3. public abstract class Decorator implements Phone {  
  4.   
  5.     private Phone phone;  
  6.   
  7.     public Decorator(Phone phone) {  
  8.         this.phone = phone;  
  9.     }  
  10.   
  11.     @Override  
  12.     public void recevieCall(String name) {  
  13.         this.phone.recevieCall(name);  
  14.     }  
  15.   
  16. }  

[java] view plain copy
  1. package com.designpattern.decorator;  
  2.   
  3. public class RingBeforeChinaMobileDecorator extends Decorator {  
  4.   
  5.     public RingBeforeChinaMobileDecorator(Phone phone) {  
  6.         super(phone);  
  7.     }  
  8.   
  9.     @Override  
  10.     public void recevieCall(String name) {  
  11.         System.out.println("step ring before recevie " + name + "call");  
  12.         super.recevieCall(name);  
  13.     }  
  14.   
  15. }  

[java] view plain copy
  1. package com.designpattern.decorator;  
  2.   
  3. public class AdAfterChinaMobileDecorator extends Decorator {  
  4.   
  5.     public AdAfterChinaMobileDecorator(Phone phone) {  
  6.         super(phone);  
  7.     }  
  8.   
  9.     @Override  
  10.     public void recevieCall(String name) {  
  11.         super.recevieCall(name);  
  12.         System.out.println("step ad after recevie " + name + " call");  
  13.     }  
  14.   
  15. }  

[java] view plain copy
  1. package com.designpattern.decorator;  
  2.   
  3. public class Client {  
  4.     public static void main(String[] args) {  
  5.         Phone phone = new ChinaMobile();  
  6.         Decorator decorator = new RingBeforeChinaMobileDecorator(phone);  
  7.         decorator.recevieCall("andimuise");  
  8.         System.out  
  9.                 .println("**************************************************");  
  10.   
  11.         decorator = new AdAfterChinaMobileDecorator(phone);  
  12.         decorator.recevieCall("halberd");  
  13.         System.out  
  14.                 .println("**************************************************");  
  15.   
  16.         decorator = new RingBeforeChinaMobileDecorator(  
  17.                 new AdAfterChinaMobileDecorator(phone));  
  18.         decorator.recevieCall("teacher");  
  19.         System.out  
  20.                 .println("**************************************************");  
  21.     }  
  22. }  
最終輸出結果為,很明顯在第三次輸出的時候我想同時實現兩種效果,就把另一個裝飾類為為了其中一個裝飾類的屬性,因為無論是裝飾類還是真實類他們是實現的共同的介面,這樣就對實現提供了很好的效果
[html] view plain copy
  1. step ring before recevie andimuisecall  
  2. step recevie andimuise call  
  3. **************************************************  
  4. step recevie halberd call  
  5. step ad after recevie halberd call  
  6. **************************************************  
  7. step ring before recevie teachercall  
  8. step recevie teacher call  
  9. step ad after recevie teacher call  
  10. **************************************************  

相關文章