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

Java 設計模式實戰:裝飾器模式在 JDK I/O 體系中的經典應用與自定義輸出流開發

     編輯:Java 相關知識

裝飾器模式核心思想

動態地給對象添加額外職責,相比生成子類更靈活。核心角色:

  • Component:抽象構件接口 (如 OutputStream)
  • ConcreteComponent:具體構件 (如 FileOutputStream)
  • Decorator:抽象裝飾者,持有 Component 引用 (如 FilterOutputStream)
  • ConcreteDecorator:具體裝飾 (如 BufferedOutputStream, DataOutputStream)

JDK I/O 體系中的裝飾器實現

1. Component:OutputStream

public abstract class OutputStream implements Closeable, Flushable {
    public abstract void write(int b) throws IOException;
    // 其他 write(byte[]), flush(), close()...
}

2. ConcreteComponent:FileOutputStream 等

public class FileOutputStream extends OutputStream {
    // 實現 write(int b) 寫入文件
    // 構造函數接受文件路徑/File/FileDescriptor
}

同類還有 ByteArrayOutputStream、PipedOutputStream。

3. Decorator:FilterOutputStream

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,構成嵌套鏈;默認方法直接轉發,子類覆寫實現具體裝飾邏輯。

4. ConcreteDecorator:BufferedOutputStream

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; }
    }
}

裝飾邏輯:引入緩衝區,批量寫入提升性能。

5. ConcreteDecorator:DataOutputStream

提供 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

總結與延伸

  • JDK 中 InputStream/Reader/Writer 體系同樣大量使用裝飾器模式。
  • 裝飾器模式優勢:運行時動態組合、避免類爆炸、單一職責、開閉原則。
  • 缺點:產生大量小對象,調試時堆棧較深;可結合構建者模式簡化構造。
  • Swing 的 Border、ScrollPane、RMI 的 Stub/Proxy 也是裝飾器變體應用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved