設計模式之(五)——裝飾模式
裝飾模式,顧名思義就是對原有的物件進行裝飾,新增新的東西。裝飾模式可以在不創造更多的子類的模式下,將物件的功能加以擴充套件。
講到裝飾模式不得不說,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。
然而可能我們需要裝飾的功能不止一個,這是我們需要將功能 抽象成一個裝飾類
舉個例子:
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 來裝飾就形成了一個具有儲存緩衝區的檔案流讀的功能了。
從上述 講解的裝飾模式可以看出來,這就是使用裝飾模式實現功能的新增。讓資料以流的形式輸入輸出,然後存放在快取區內進行接下來的操作。
只要弄懂了裝飾模式的意思,具體的實現可以根據需要實現功能的新增。
水平有限,不吝賜教。