Java設計模式學習記錄-裝飾模式

來源:互聯網
上載者:User

標籤:總結   tput   測試   不同   lte   final   name   controls   style   

前言

裝飾模式也是一種結構型模式,主要是目的是相對於類與類之間的繼承關係來說,使用裝飾模式可以降低耦合度。JDK中有不少地方都使用到了裝飾模式,例如Java的各種I/O流,javax.swing包中一些圖形介面構件功能的增強等地方都運用了裝飾模式。 

裝飾模式定義

裝飾模式的定義是:在不改變原類檔案以及不使用繼承的情況下,動態擴充一個對象的功能。裝飾模式是通過建立一個封裝對象來實現的,也就是用裝飾來包裹真實的對象。

舉例

還是老規矩,舉例說明,在給親朋好友過生日時會買生日蛋糕,然後生日蛋糕又有各種各樣的輔料來進行裝飾,例如:奶油,水果,芝士,巧克力等等。如果沒有這些輔料來進行裝飾,就是普通的雞蛋糕。所以我們可以把做蛋糕的這個過程來用代碼實現出來:

首先定義蛋糕介面

/** * 蛋糕 */public interface CakeGoods {    /**     * 展示蛋糕     */    void showCake();    /**     * 展示價格     */    BigDecimal showPrice();}

具體的雞蛋糕

/** * 雞蛋糕 */@Datapublic class SpongeCake implements CakeGoods{    //蛋糕名稱    private String name;    //蛋糕價格    private BigDecimal price;    public SpongeCake(String name,BigDecimal price){        this.name = name;        this.price = price;    }    /**     * 展示蛋糕     */    @Override    public void showCake() {        System.out.println("的"+this.name+"蛋糕");    }    /**     * 展示價格     */    @Override    public BigDecimal showPrice() {        return this.price;    }}

輔料的抽象類別

/** * 輔料的抽象類別 */public abstract class Decorator implements CakeGoods{    private CakeGoods cakeGoods;    public void setCakeGoods(CakeGoods cakeGoods){        this.cakeGoods = cakeGoods;    }    /**     * 展示蛋糕     */    @Override    public void showCake() {        cakeGoods.showCake();    }    /**     * 展示價格     */    @Override    public BigDecimal showPrice() {        return cakeGoods.showPrice();    }}

水果

/** * 水果 */public class Fruits extends Decorator {    /**     * 展示蛋糕     */    @Override    public void showCake() {        System.out.print("加水果");        super.showCake();    }    /**     * 展示價格     */    @Override    public BigDecimal showPrice() {        return new BigDecimal(20.00).add(super.showPrice());    }}

奶油

/** * 奶油 */public class Cream extends Decorator {    /**     * 展示蛋糕     */    @Override    public void showCake() {        System.out.print("加奶油");        super.showCake();    }    /**     * 展示價格     */    @Override    public BigDecimal showPrice() {        return new BigDecimal(15.00).add(super.showPrice());    }}

測試

public class Tests {    public static void main(String[] args) {                //製造雞蛋糕        CakeGoods cakeGoods = new SpongeCake("生日祝福",new BigDecimal(50));        Decorator cream = new Cream();        Decorator fruits = new Fruits();        //加奶油        cream.setCakeGoods(fruits);        //加水果        fruits.setCakeGoods(cakeGoods);                //展示        cream.showCake();        System.out.println("的價格是:"+cream.showPrice()+"元");    }}

運行結果:

加奶油加水果的生日祝福蛋糕的價格是:85元

 上面的這個蛋糕製造的例子使用的就是裝飾模式,在為雞蛋糕SpongeCake進行擴充的時候並沒有影響它原來的類的結構,也沒有使用繼承的關係,最終卻達到了裝飾的目的。下面我們來分析一下裝飾模式具體是由那幾部分組成。

裝飾模式的結構

裝飾模式的結構圖如上所示,主要由以下幾個角色群組成。

抽象構件角色:(的CakeGoods)定義一個抽象介面,以規範準備接受裝飾的對象,想當於Java中的IO流裡的InputStram/OutputStream和Reader/Writer。

具體的構件角色:(的SpongeCake)定義一個將要接受裝飾的類,相當於I/O流裡面的FileOutputStream和FileInputStream。

裝飾角色:(的Decorator)定義一個持有抽象構件角色的引用,並定義一個與抽象構件一直的介面。相當於I/O裡面的FilterOutputStream和FilterInputStream。

具體的裝飾角色:(的Fruits和Cream)負責各構件角色對象加上相應的裝飾品,相當於I/O流裡的BufferedOutputStream、BufferedInputStream。

在使用的時候,必須擴充CakeGoods的功能,但是我們是通過Fruits和Cream來對CakeGoods進行擴充的,所以相對於CakeGoods來說無需知道Decorator的存在,就能擴充功能了。

總結裝飾模式的優點
  1. 對於擴充一個對象的功能,裝飾模式比繼承更加靈活性,不會導致類的個數急劇增加。例如上面的例子如果想增加一個棗糕或是一個巧克力輔料,無需修改現有代碼,只需將棗糕作為CakeGoods的一個子類,以及Decorator的一個子類即可。
  2. 可以動態擴充一個對象的功能。
  3. 可以對一個對象進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合,得到功能更為強大的對象。
  4. 具體構件類與具體裝飾類可以獨立變化,使用者可以根據需要增加新的具體構件類和具體裝飾類,原有類庫代碼無須改變,符合“開閉原則”。
裝飾模式的缺點
  1. 使用裝飾模式進行系統設計時將產生很多小對象,這些對象的區別在於它們之間相互串連的方式有所不同,而不是它們的類或者屬性值有所不同,大量小對象的產生勢必會佔用更多的系統資源,在一定程式上影響程式的效能。
  2. 裝飾模式提供了一種比繼承更加靈活機動的解決方案,但同時也意味著比繼承更加易於出錯,排錯也很困難,對於多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較為繁瑣。
適用情境

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

當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴充和維護時可以使用裝飾模式。不能採用繼承的情況主要有兩類:第一類是系統中存在大量獨立的擴充,為支援每一種擴充或者擴充之間的組合將產生大量的子類,使得子類數目呈爆炸性增長;第二類是因為類已定義為不能被繼承(如Java語言中的final類)。

 

加油,給自己打氣,克服惰性!!!

 

 

 

 

 

想瞭解更多的設計模式請查看Java設計模式學習記錄-GoF設計模式概述。

 

 

 

 

 

Java設計模式學習記錄-裝飾模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.