首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java IO 裝飾器模式深度解析:OutputStream 體系源碼級剖析與自定義擴展

     編輯:Java 程式設計入門

裝飾器模式核心意圖

動態地給對象添加職責,比生成子類更靈活。關鍵:被裝飾者與裝飾者共享同一接口/父類,客戶端無感知;裝飾者持有被裝飾者引用,轉發請求並在前後執行額外邏輯。

Java IO 裝飾器結構圖解

Component (java.io.OutputStream) ← 抽象父類,定義 write(int b)
    │
    ├─ ConcreteComponent: FileOutputStream, ByteArrayOutputStream, PipedOutputStream
    │
    └─ Decorator (java.io.FilterOutputStream) ← 抽象裝飾基類,持有 out 引用
            │
            ├─ BufferedOutputStream  (緩衝)
            ├─ DataOutputStream      (基本類型寫入)
            ├─ PrintStream           (print/println、自動flush、異常吞沒)
            ├─ ObjectOutputStream    (對象序列化)
            ├─ CipherOutputStream    (加密)
            ├─ GZIPOutputStream      (壓縮)
            └─ ... (用戶自定義)

源碼級剖析:OutputStream → FilterOutputStream → DataOutputStream

1. Component: OutputStream (JDK 1.8 精簡)

public abstract class OutputStream implements Closeable, Flushable {
    public abstract void write(int b) throws IOException; // 核心抽象方法
    public void write(byte[] b) throws IOException { write(b, 0, b.length); }
    public void write(byte[] b, int off, int len) throws IOException {
        for (int i = 0; i < len; i++) write(b[off + i]); // 默認逐字節寫入 (子類通常覆寫優化)
    }
    public void flush() throws IOException {}
    public void close() throws IOException {}
}

2. ConcreteComponent: FileOutputStream (本地文件輸出)

public class FileOutputStream extends OutputStream {
    private final FileDescriptor fd;
    // native 方法直接調用 OS write
    private native void write(int b) throws IOException;
    private native void write(byte[] b, int off, int len) throws IOException;
    // ... 文件打開/關閉/獲取 Channel 等
}

3. Decorator 基類: FilterOutputStream

public class FilterOutputStream extends OutputStream {
    protected final OutputStream out; // 持有被裝飾者引用
    protected FilterOutputStream(OutputStream out) { this.out = out; }
    
    // 默認轉發實現,子類可選擇性覆寫
    public void write(int b) throws IOException { out.write(b); }
    public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); }
    public void flush() throws IOException { out.flush(); }
    public void close() throws IOException { out.close(); }
}

4. ConcreteDecorator: DataOutputStream (基本類型序列化)

public class DataOutputStream extends FilterOutputStream implements DataOutput {
    public DataOutputStream(OutputStream out) { super(out); }
    
    // 新增業務方法:寫入基本類型
    public final void writeInt(int v) throws IOException {
        out.write((v >>> 24) & 0xFF);
        out.write((v >>> 16) & 0xFF);
        out.write((v >>> 8) & 0xFF);
        out.write(v & 0xFF);
    }
    public final void writeUTF(String str) throws IOException { /* Modified UTF-8 編碼 */ }
    // ... writeBoolean, writeLong, writeDouble 等
    
    // 繼承 write(byte[]) 等轉發方法,無需覆寫
}

經典使用模式:層層包裝

// 寫入文件、緩衝、基本類型、對象序列化
OutputStream out = new ObjectOutputStream(
    new DataOutputStream(
        new BufferedOutputStream(
            new FileOutputStream("data.bin"))));

out.writeInt(42);
out.writeUTF("Hello");
out.writeObject(new User("Alice"));
out.close(); // 關閉鏈路自動級聯關閉底層流

實戰:自定義裝飾器 — 統計寫入字節數的 CountingOutputStream

public class CountingOutputStream extends FilterOutputStream {
    private long bytesWritten = 0;
    
    public CountingOutputStream(OutputStream out) { super(out); }
    
    @Override
    public void write(int b) throws IOException {
        out.write(b);
        bytesWritten++;
    }
    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        out.write(b, off, len);
        bytesWritten += len;
    }
    
    public long getBytesWritten() { return bytesWritten; }
    public void resetCount() { bytesWritten = 0; }
}

// 使用
CountingOutputStream counter = new CountingOutputStream(new FileOutputStream("log.txt"));
counter.write("Hello".getBytes());
System.out.println("Written: " + counter.getBytesWritten() + " bytes"); // 5

裝飾器 vs 繼承 vs 代理 對比

維度裝飾器繼承代理
關系組合 (Has-A)繼承 (Is-A)組合 (Has-A)
靈活性運行時動態組合編譯期靜態運行時可換
職責增強/添加功能特化/覆寫控制訪問/遠程/延遲
透明性完全透明 (同接口)透明 (是子類)透明 (同接口)
典型場景IO 流、集合包裝、Servlet Filter模板方法、框架擴展點遠程調用、AOP、懶加載

現代化演進:NIO.2 / Reactive Streams

  • java.nio.channels.AsynchronousFileChannel + CompletionHandler:異步非阻塞 IO,無裝飾器鏈路。
  • java.util.stream.Stream / reactor.core.publisher.Flux:聲明式數據流管道,操作符鏈替代裝飾器嵌套。
  • 但裝飾器思想永存:Servlet Filter Chain、Spring Interceptor、Dubbo Filter、Netty ChannelHandler 皆為裝飾器模式變體。

掌握 IO 裝飾器源碼結構,能讀懂所有基於流/鏈路/管道的中間件架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved