1. 程式人生 > >設計模式之(五)——裝飾模式

設計模式之(五)——裝飾模式

裝飾模式,顧名思義就是對原有的物件進行裝飾,新增新的東西。裝飾模式可以在不創造更多的子類的模式下,將物件的功能加以擴充套件。
講到裝飾模式不得不說,java 的 io 就是有利用裝飾模式設計。
寫兩句程式碼就清楚了。
1、socket程式設計,讀控制檯輸入的字元,我們會寫:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

2、檔案讀(寫):

 BufferedReader br = new BufferedReader(new FileReader(file));

這裡就使用了裝飾模式,這其實就是將 InputStreamReader 物件和 FileReader 用BufferedReader 來進行裝飾,然後就會得到了一個具有了快取buff 功能的流讀取方式了。

這裡我們稍微總結一下。
裝飾模式需要幾個材料才能實現:
1、 抽象構建角色(Component):無論是抽象類還是介面,這裡是 待裝飾物件 和新增的 裝飾物件 都需要有一個統一的介面實現(或繼承)這樣才能真正的實現裝飾。(java io中如 InputStream/OutputStream 和Reader/Writer類)。

2、 具體的構建角色(ConcreteComponent):實現具體的待裝飾的物件。我們都需要一個統一的“空白”物件,我們之後是給這個“空白”物件進行裝飾,新增功能。(java io中如 FileOutputStream 和 FileInputStream)。

3、裝飾角色(Docorator):統一的裝飾物件

。這裡可以認為是定義需要新增的裝飾的一個抽象。這裡可以根據 裝飾的樣式不同 定義不同的子類,在進行新增時互不干擾。(裝飾的多變可以有)。

4、具體的裝飾角色(ConcreteDecorator):真正意義上的裝飾,即新增的功能物件。(java io中如 BufferedOutputStream 和 BufferedInputStream,DataOutputStream 和 DataInputSrtream)。

這裡我們來解釋下,如圖:
這裡寫圖片描述

這裡 有一個 待裝飾ConcreteComponent 只有裝飾 Docorator 後才能形成一個整體 Component
然而可能我們需要裝飾的功能不止一個,這是我們需要將功能 抽象成一個裝飾類

,然後新增功能時可以根據需要進行新增 裝飾A 或者 裝飾B 或者兩者都加(兩者都加和上一層的裝飾類似)。

舉個例子:

interface Component {
    public void doSth();
}

class ConcreteComponent implements Component {
    @Override
    public void doSth() {
        System.out.println("功能X");
    }
}

class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void doSth() {
        component.doSth();
    }
}

class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void doSth() {
        super.doSth();
        System.out.println("功能A");
    }
}

class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void doSth() {
        super.doSth();
        System.out.println("功能B");
    }
}

public class Test {
    public static void main(String[] args) {
        Component component = new ConcreteDecoratorA(
                              new ConcreteDecoratorB(
                              new ConcreteComponent()));
        component.doSth();
    }
}

執行結果就是在實現自身功能的同時實現了新增的功能。如圖:
這裡寫圖片描述
這裡就是先將 B 的的功能裝飾上去,然後將 A 的功能裝飾上去,這樣就形成了新的類,同時實現 X,B,A 的功能。

不過這裡的裝飾類是比較通常的實現方法,這裡也有簡潔的實現方式,正如我上面說的那樣,比如 :
1、直接在 帶裝飾類 中新增功能時,就不需要介面(抽象類)Component 。只需新增的裝飾是帶裝飾類的子類即可。
2、裝飾新增的只有一個物件功能時我們可以不需要 裝飾類的抽象層 Decorator

那麼現在,我們再回頭再看看java 的 io。

public abstract class Reader 

public class BufferedReader extends Reader

public class InputStreamReader extends Reader 

public class FileReader extends InputStreamReader

BufferedReader br = new BufferedReader(new FileReader(file));

我們可以看到 上述 BufferedReader ,InputStreamReader ,FileReader 的祖先都是 Reader。
然後 FileReader 用 BufferedReader 來裝飾就形成了一個具有儲存緩衝區的檔案流讀的功能了。

從上述 講解的裝飾模式可以看出來,這就是使用裝飾模式實現功能的新增。讓資料以流的形式輸入輸出,然後存放在快取區內進行接下來的操作。

只要弄懂了裝飾模式的意思,具體的實現可以根據需要實現功能的新增。

水平有限,不吝賜教。