作者:Grey
原文地址:
裝飾器模式是一種結構型模式。
顧名思義,就是對某個方法或者物件進行裝飾,舉個簡單的例子,有個圓形類 Circle,我需要把這個圓形的塗上紅色,其實就是新增一個裝飾器來裝飾這個圓形類。
如果要讓裝飾器通用一些,可以處理圓形類對應的抽象類 Sharp ,那麼對於任意 Sharp 的子類,都可以用紅色裝飾器來塗紅色。
範例程式碼如下
我們先定義 Sharp 這個抽象類
public abstract class Sharp {
protected abstract void draw();
}
然後我們定義 Sharp 的裝飾類 SharpDecorator ,這個類是所有裝飾器類的抽象類,後續的裝飾器只需要實現這個抽象類就可以對 Sharp 進行各種裝飾了,
public abstract class SharpDecorator extends Sharp {
protected Sharp decoratedSharp;
public SharpDecorator(Sharp decoratedSharp) {
this.decoratedSharp = decoratedSharp;
}
}
紅色裝飾器實現這個抽象類即可:
public class RedSharpDecorator extends SharpDecorator {
public RedSharpDecorator(Sharp decoratedSharp) {
super(decoratedSharp);
}
private static void redIt() {
System.out.println("[RED]");
}
@Override
protected void draw() {
redIt();
this.decoratedSharp.draw();
redIt();
}
}
主方法呼叫的時候只需要:
new RedSharpDecorator(new Circle()).draw();
UML 圖如下:
說明:
裝飾器類和原始類繼承同樣的父類別,這樣我們可以對原始類「巢狀」多個裝飾器類。
裝飾器類是對功能的增強,這也是裝飾器模式應用場景的一個重要特點。符合「組合關係」這種程式碼結構的設計模式有很多,比如代理模式、橋接模式,還有現在的裝飾器模式。儘管它們的程式碼結構很相似,但是每種設計模式的意圖是不同的。就拿比較相似的代理模式和裝飾器模式來說:
代理模式中,代理類附加的是跟原始類無關的功能;
裝飾器模式中,裝飾器類附加的是跟原始類相關的增強功能。
在 JDK 中,BufferedInputStream 、 DataInputStream 並非繼承自 InputStream ,而是另外一個叫 FilterInputStream 的類。
這是因為 InputStream 是一個抽象類而非介面,而且它的大部分函數(比如 read()
、available()
)都有預設實現,按理來說,我們只需要在 BufferedInputStream 類中重新實現那些需要增加快取功能的函數就可以了,其他函數只需要複用 InputStream 的預設實現。但實際上,這樣做是行不通的。對於即便是不需要增加快取功能的函數來說,BufferedInputStream 還是必須把它重新實現一遍,簡單包裹對 InputStream 物件的函數呼叫。那 BufferedInputStream 類就無法將最終讀取資料的任務,委託給傳遞進來的 InputStream 物件來完成,DataInputStream 也存在跟 BufferedInputStream 同樣的問題。為了避免程式碼重複,Java I/O 包中抽象出了一個裝飾器父類別 FilterInputStream,包裝了 InputStream 的預設實現
package java.io;
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public long skip(long n) throws IOException {
return in.skip(n);
}
public int available() throws IOException {
return in.available();
}
public void close() throws IOException {
in.close();
}
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
public synchronized void reset() throws IOException {
in.reset();
}
public boolean markSupported() {
return in.markSupported();
}
}
InputStream 的所有的裝飾器類( BufferedInputStream 和 DataInputStream )都繼承自這個裝飾器父類別。這樣,裝飾器類只需要實現它需要增強的方法就可以了,其他方法繼承裝飾器父類別的預設實現。
其他應用
Java 中的 I/O 流, Read/InputStream
,Write/OutputStream
;
Java 中的 UnmodifiableCollection
;
Spring 中的 HttpHeadResponseDecorator
, 還有對 Cache 的裝飾類 TransactionAwareCacheDecorator
。
本文來自部落格園,作者:Grey Zeng,轉載請註明原文連結:https://www.cnblogs.com/greyzeng/p/16878615.html