裝飾者模式(轉)

設計模式讀書筆記-----裝飾者模式

 

        咱們都知道,可使用兩種方式給一個類或者對象添加行爲。html

        一是使用繼承。繼承是給一個類添加行爲的比較有效的途徑。經過使用繼承,可使得子類在擁有自身方法的同時,還能夠擁有父類的方法。可是使用繼承是靜態的,在編譯的時候就已經決定了子類的行爲,咱們不便於控制增長行爲的方式和時機。java

        二是使用關聯。組合即將一個對象嵌入到另外一個對象中,由另外一個對象來決定是否引用該對象來擴展本身的行爲。這是一種動態的方式,咱們能夠在應用程序中動態的控制。設計模式

        與繼承相比,關聯關係的優點就在於不會破壞類的封裝性,且具備較好的鬆耦合性,可使系統更加容易維護。可是它的缺點就在於要建立比繼承更多的對象。ide

 

        

1、基本定義

裝飾者模式,動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更加有彈性的替代方案。

 

 

 

        <h1;">2、模式結構裝飾者模式UML結構圖。post

        Component: 抽象構件。是定義一個對象接口,能夠給這些對象動態地添加職責。測試

        ConcreteComponent:具體構件。是定義了一個具體的對象,也能夠給這個對象添加一些職責。this

        Decorator: 抽象裝飾類。是裝飾抽象類,繼承了Component,從外類來擴展Component類的功能,但對於Component來講,是無需知道Decorator存在的。編碼

        ConcreteDecorator:具體裝飾類,起到給Component添加職責的功能。url

 

        

3、實現裝飾者模式

 

        結構圖以下:spa

        裝飾者模式提供了一個比較好的解決方案。

        編碼實現:

        Component  Beverage.java

複製代碼
1 public abstract class Beverage {
2     protected String description = "Unknown Beverage";
3 
4     public String getDescription() {
5         return description;
6     }
7 
8     public abstract double cost();
9 }
複製代碼

 

        四個組件:HouseBlend.java

複製代碼
 1 public class HouseBlend extends Beverage {
 2 
 3     public HouseBlend(){
 4         description = "HouseBlend";
 5     }
 6     
 7     @Override
 8     public double cost() {
 9         return 0.89;
10     }
11 
12 }
複製代碼

 

        DarkRoast.java

複製代碼
 1 public class DarkRoast extends Beverage {
 2     public DarkRoast(){
 3         description = "DarkRoast";
 4     }
 5     @Override
 6     public double cost() {
 7         return 1.05;
 8     }
 9 
10 }
複製代碼

 

        Espresso.java

複製代碼
 1 public class DarkRoast extends Beverage {
 2     public DarkRoast(){
 3         description = "DarkRoast";
 4     }
 5     @Override
 6     public double cost() {
 7         return 1.05;
 8     }
 9 
10 }
複製代碼

 

        Decat.java

複製代碼
 1 public class Decat extends Beverage {
 2     public Decat(){
 3         description = "Decat";
 4     }
 5         
 6     @Override
 7     public double cost() {
 8         return 0.99;
 9     }
10 
11 }
複製代碼

 

        CondimentDecorator.java

1 public abstract class CondimentDecorator extends Beverage{
2     public abstract String getDescription();
3 }

 

        Milk.java

複製代碼
 1 public class Milk extends CondimentDecorator {
 2     Beverage beverage;
 3     
 4     public Milk(Beverage beverage){
 5         this.beverage = beverage;
 6     }
 7     
 8     @Override
 9     public String getDescription() {
10         return beverage.getDescription() + " , Milk";
11     }
12 
13     @Override
14     public double cost() {
15         return beverage.cost() + 0.3;
16     }
17 }
複製代碼

 

        Mocha.java

複製代碼
 1 public class Mocha extends CondimentDecorator {
 2     Beverage beverage;
 3     public Mocha(Beverage beverage){
 4         this.beverage = beverage;
 5     }
 6     
 7     @Override
 8     public String getDescription() {
 9         return beverage.getDescription() + " , Mocha";
10     }
11 
12     @Override
13     public double cost() {
14         return beverage.cost() + 0.20;
15     }
16 
17 }
複製代碼

 

        Soy.java

複製代碼
 1 public class Soy extends CondimentDecorator{
 2     Beverage beverage;
 3     public Soy(Beverage beverage) {
 4         this.beverage = beverage;
 5     }
 6     @Override
 7     public String getDescription() {
 8         return beverage.getDescription() + " , Soy";
 9     }
10 
11     @Override
12     public double cost() {
13         return beverage.cost() + 0.10;
14     }
15 
16 }
複製代碼

 

        Whip.java

複製代碼
 1 public class Whip extends CondimentDecorator {
 2     Beverage beverage;
 3     public Whip(Beverage beverage){
 4         this.beverage = beverage;
 5     }
 6     @Override
 7     public String getDescription() {
 8         return beverage.getDescription() + " , Whip";
 9     }
10 
11     @Override
12     public double cost() {
13         return beverage.cost() + 0.20;
14     }
15 
16 }
複製代碼

 

        測試程序

複製代碼
 1 public class StarbuzzCoffee {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         Beverage beverage = new Espresso();
 8         System.out.println(beverage.getDescription() + " $" + beverage.cost());
 9         
10         Beverage beverage2 = new DarkRoast();
11         beverage2 = new Mocha(beverage2);
12         beverage2 = new Mocha(beverage2);
13         beverage2 = new Whip(beverage2);
14         System.out.println(beverage2.getDescription() + " $" + beverage2.cost());    
15     }
16 
17 }
複製代碼

 

        運行結果

        <h14、模式的優缺點< h1="">

 

           一、裝飾者模式能夠提供比繼承更多的靈活性

           二、能夠經過一種動態的方式來擴展一個對象的功能,在運行時選擇不一樣的裝飾器,從而實現不一樣的行爲。

           三、經過使用不一樣的具體裝飾類以及這些裝飾類的排列組合,能夠創造出不少不一樣行爲的組合。可使用多個具體裝飾類來裝飾同一對象,獲得功能更爲強大的對象。

           四、具體構件類與具體裝飾類能夠獨立變化,用戶能夠根據須要增長新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有代碼無須改變,符合「開閉原則」。

 

        

缺點

 

           一、會產生不少的小對象,增長了系統的複雜性

           二、這種比繼承更加靈活機動的特性,也同時意味着裝飾模式比繼承更加易於出錯,排錯也很困難,對於屢次裝飾的對象,調試時尋找錯誤可能須要逐級排查,較爲煩瑣。

 

       

5、模式的適用場景

一、在不影響其餘對象的狀況下,以動態、透明的方式給單個對象添加職責。

 

                 二、須要動態地給一個對象增長功能,這些功能也能夠動態地被撤銷。  當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴展和維護時。

 

        6、總結nbsp;                一、 組合和委託能夠在運行時動態的添加新的行爲,而繼承是靜態的,在系統編譯時就已經決定了對象的行爲。

                 二、裝飾者模式意味着一羣裝飾者類,這些類用來包裝具體組件

                 三、裝飾者能夠在被裝飾者的行爲前面或者後面加上本身的行爲,甚至能夠將被裝飾者的行爲整個取代掉,從而達到特定的目的。

                 四、能夠用多個裝飾者包裝一個組件。

                 五、裝飾者通常對於組件的客戶是透明的,除非客戶程序依賴於組件的具體類型。

                 六、裝飾者會致使設計中出現許多的小對象,若是過分的使用,會讓系統變得更加複雜。

                 七、裝飾者和被裝飾者對象有相同的超類型。

 

 

做者: chenssy 
出處: http://www.cnblogs.com/chenssy/ 

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息