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

前言

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

裝飾模式

定義

裝飾模式的定義是:在不改變原類文件以及不使用繼承的狀況下,動態的擴展一個對象的功能。裝飾模式是經過建立一個包裝對象來實現的,也就是用裝飾來包裹真實的對象。java

舉例

仍是老規矩,舉例說明,在給親朋好友過生日時會買生日蛋糕,而後生日蛋糕又有各類各樣的輔料來進行裝飾,例如:奶油,水果,芝士,巧克力等等。若是沒有這些輔料來進行裝飾,就是普通的雞蛋糕。因此咱們能夠把作蛋糕的這個過程來用代碼實現出來:設計模式

首先定義蛋糕接口ide

/**
 * 蛋糕
 */
public interface CakeGoods {

    /**
     * 展現蛋糕
     */
    void showCake();

    /**
     * 展現價格
     */
    BigDecimal showPrice();
}

具體的雞蛋糕post

/**
 * 雞蛋糕
 */
@Data
public 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());
    }
}

測試ui

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()+"元");
    }

}

運行結果:this

加奶油加水果的生日祝福蛋糕
的價格是: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設計模式概述

相關文章
相關標籤/搜索