設計模式學習之Decorator模式
繼續學習設計模式,今天是裝飾者模式,它屬于結構型模式,首先還是它的基本概念:
- 裝飾者模式:
動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。
- 適用性:
- 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
- 處理那些可以撤消的職責。
- 當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
- 我的理解是:
裝飾者模式就好比一個個wrapper(包裝器),將一個對象一層層的包裝,然后返回包裝后的對象,就好比你在網上購買了一個電飯鍋,那么這個電飯鍋就是最原始的對象,而商家可能會在發貨時進行一個初步包裝,首先將電飯鍋用一層泡沫包起來,然后裝入一個紙箱,接著交給快遞公司,然后快遞公司收到這個物品后,還要進行二次包裝,即使用快遞公司專門的盒子裝起來(或者用麻袋裝好),然后貼上膠布開始運輸,客戶收到的這個箱子自后,一層層解開包裝,最后拿出電飯鍋。那么所有包裝這個電飯鍋的東西,像泡沫啊,紙箱啊,盒子啊,膠布啊,都可以算作裝飾者,裝飾者將原來的對象裝飾完之后,會生成一個裝飾后的對象,使源對象加上各種裝飾品。所以,既然裝飾者依賴于被裝飾的對象,那么,裝飾者在實現時就理所當然需要一個被裝飾的對象的引用了,然后裝飾完之后該引用就會指向裝飾后的對象了。
所以,裝飾者模式一定要搞明白裝飾者的使用方式。 - 另外,因為裝飾者能夠替換源對象,所以在實際實現時需要將裝飾者和源對象繼承同一個父類(這個和實際有所不同,實際中,裝飾者和源對象是不同的對象種類,但設計總歸設計,不能總是和實際完美的相符,是需要一些靈活的處理的,而且這種設計的其本質是裝飾者裝飾之后的對象和源對象屬于同一個父類,就好比電飯鍋和裝在盒子里的電飯鍋都是電飯鍋一樣,但盒子并不是電飯鍋)
- 還有一點就是,實際實現的裝飾者,是裝飾源對象的某個方法,相當于將被裝飾的對象的某個方法增添或替換成某種方法而不改變源對象的代碼和結構,就相當于動態的改變某種功能。
代碼:
1 //被裝飾者接口 2 public interface IProduct 3 { 4 public void transport(); 5 } 6 //具體的被裝飾者 7 public class Product implements IProduct 8 { 9 protected String name; 10 public Product(String name) 11 { 12 this.name=name; 13 } 14 public void transport() 15 { 16 System.out.println("原始的產品:"+this.name); 17 System.out.println("運輸..."); 18 } 19 } 20 //裝飾者類 21 public class Decorator implements IProduct 22 { 23 protected IProduct product; 24 protected String name; 25 public Decorator(IProduct product, String name) 26 { 27 this.product=product; 28 this.name=name; 29 } 30 public void transport() 31 { 32 System.out.println("包裝"); 33 if(this.product != NULL) 34 { 35 this.product.transport(); 36 } 37 } 38 } 39 //具體的裝飾者1 40 public class Decorator1 extends Decorator 41 { 42 public void Decorator1(IProduct product) 43 { 44 this.product=product; 45 this.name="泡沫"; 46 } 47 public void transport() 48 { 49 System.out.println("用"+this.name+"包裝"); 50 if(this.pruduct != NULL) 51 { 52 this.product.transport(); 53 } 54 } 55 } 56 //具體的裝飾者2 57 public class Decorator2 extends Decorator 58 { 59 public void Decorator1(IProduct product) 60 { 61 this.product=product; 62 this.name="紙盒"; 63 } 64 public void transport() 65 { 66 System.out.println("用"+this.name+"包裝"); 67 if(pruduct != NULL) 68 { 69 this.product.method1(); 70 } 71 } 72 } 73 public class Test 74 { 75 public static void main(String argv[]) 76 { 77 IProduct product=new Product("電飯鍋"); 78 product=new Decorator1(product);//用泡沫包裝 79 product=new Decorator2(product);//用紙盒包裝 80 /*之后product對象就是被紙盒包裝又被泡沫包裝的對象了*/ 81 product.transport();//從外到里依次輸出包裝物直到原產品,最后進行運輸 82 } 83 }
作者:everdom
出處:http://everdom.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。

浙公網安備 33010602011771號