動態地給對象添加額外職責,相比生成子類更靈活。核心角色:
OutputStream)FileOutputStream)FilterOutputStream)BufferedOutputStream, DataOutputStream)public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int b) throws IOException;
// 其他 write(byte[]), flush(), close()...
}
public class FileOutputStream extends OutputStream {
// 實現 write(int b) 寫入文件
// 構造函數接受文件路徑/File/FileDescriptor
}
同類還有 ByteArrayOutputStream、PipedOutputStream。
public class FilterOutputStream extends OutputStream {
protected final OutputStream out; // 持有被裝飾對象引用
public FilterOutputStream(OutputStream out) { this.out = out; }
public void write(int b) throws IOException { out.write(b); } // 轉發
// 其他方法同理轉發...
}
關鍵設計:構造函數強制傳入 OutputStream,構成嵌套鏈;默認方法直接轉發,子類覆寫實現具體裝飾邏輯。
public class BufferedOutputStream extends FilterOutputStream {
private byte[] buf;
private int count;
public synchronized void write(int b) throws IOException {
if (count >= buf.length) flushBuffer(); // 緩衝區滿則刷新
buf[count++] = (byte) b;
}
private void flushBuffer() throws IOException {
if (count > 0) { out.write(buf, 0, count); count = 0; }
}
}
裝飾邏輯:引入緩衝區,批量寫入提升性能。
提供 writeInt(), writeUTF() 等類型化寫入方法,內部轉換為字節調用 out.write()。
// 多層裝飾:文件輸出 + 緩衝 + 數據類型化
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("data.bin")));
out.writeInt(42);
out.writeUTF("Hello Decorator");
out.close(); // 關閉鏈路最外層,鏈式關閉內層
寫入時自動過濾空格字符,如 "Java I/O" → "JavaI/O"。
public class SkipSpaceOutputStream extends FilterOutputStream {
public SkipSpaceOutputStream(OutputStream out) { super(out); }
@Override
public void write(int b) throws IOException {
if (b != ' ') super.write(b); // 非空格才寫入
}
// 為性能考慮,建議覆寫 write(byte[], int, int) 批量過濾
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (int i = off; i < off + len; i++) {
if (b[i] != ' ') out.write(b[i]);
}
}
}
public class Test {
public static void main(String[] args) throws IOException {
OutputStream out = new SkipSpaceOutputStream(
new DataOutputStream(System.out));
System.out.print("Please input: ");
byte[] buf = new byte[1024];
int n = System.in.read(buf);
out.write(buf, 0, n);
out.flush();
}
}
// 輸入: a b c d e f
// 輸出: abcdef
InputStream/Reader/Writer 體系同樣大量使用裝飾器模式。