天天看點

裝飾者模式 Decorator Pattern一、是什麼二、問答三、執行個體

父博文位址:設計模式 - Design Patterns

一、是什麼

  1. 問題

    使用繼承是靜态的擴充:

    • 随着系統功能增多造成了類數量指數級增加。
    • 且基類的功能并不适用于所有子類。
  2. 尋找一個設計模式原則

    開閉原則:類應該對擴充開放,對修改關閉。換句話說:在不修改類的前提下擴充類。

  3. 裝飾者模式定義

    動态的将責任附加到對象 上。若要擴充功能,裝飾者提供了比繼承更有彈性的替代方案。

    類圖如下:

    裝飾者模式 Decorator Pattern一、是什麼二、問答三、執行個體

二、問答

  1. AbstractDecorator

    及其子類依然繼承自

    AbstractComponent

    不是嗎?

    我們依然使用了繼承,的确如此。不過這麼做的重點在于,裝飾者和被裝飾者需要是同一個類型,這很關鍵。我們隻是利用繼承達到“類型比對”,而不是利用繼承擷取“行為”。

  2. 加入行為

    我們不是通過繼承來“加入新行為”,而是通過“組合”。

  3. 為什麼裝飾者是抽象類?

    通常使用抽象類,當然Java 中也可以使用接口,此時需要把構造函數定義在各個裝飾者子類中。

三、執行個體

1.

FilterInputStream

InputStream

的裝飾器

類圖如下:

裝飾者模式 Decorator Pattern一、是什麼二、問答三、執行個體
  1. 介紹

    InputStream

    是抽象被裝飾類,

    ObjectInputStream

    ,

    FileInputStream

    ,

    ByteArrayInputStream

    等是可以被裝飾的具體元件。

    FilterInputStream

    是裝飾者類(這裡沒有設計為抽象),

    BufferedInputStream

    ,

    LineNumberInputSream

    ,

    DataInputSream

    等是具體的裝飾者類。
  2. FilterInputStream

    代碼
    public class FilterInputStream extends InputStream {
    
        protected volatile InputStream in;
    
        protected FilterInputStream(InputStream in) {
            this.in = in;
        }
    
        public int read() throws IOException {
            return in.read();
        }
    
        // others
    }
               
    可以看到,包裝類隻有一個有參數的構造函數,參數是被包裝類。包裝類可以動态的添加功能,這裡覆寫了

    read()

    并簡單的調用被包裝類的同名方法。
  3. 一個可能的用例
    裝飾者模式 Decorator Pattern一、是什麼二、問答三、執行個體

    FileInputSream

    BufferedInputSream

    裝飾,

    BufferedInputSream

    又被

    LineNumberInputSream

    裝飾。

繼續閱讀