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

畢向東 Java 基礎 Day 19:IO 流裝飾模式深度解析與自定義緩衝實現

     編輯:Java 綜合教學

裝飾設計模式核心思想

當需要在不修改原有類的前提下動態增強功能時,裝飾模式是首選。它通過組合而非繼承,將被裝飾對象傳入構造器,並在保留原有行為基礎上添加新功能。IO 流體系中 BufferedReader、LineNumberReader 皆是經典裝飾類。

裝飾模式 vs 繼承:擴展性對比

若用繼承為每種 Reader 添加緩衝功能,需創建 MyBufferReader(MyTextReader)、MyBufferReader(MyMediaReader) 等多個構造器,類爆炸嚴重。裝飾模式只需定義:

class MyBufferReader extends Reader {
    private Reader r; // 持有統一父類引用
    public MyBufferReader(Reader r) { this.r = r; }
    // 增強方法...
}

實現「組合優於繼承」,極大降低耦合,符合開閉原則。

自定義緩衝讀取器:逐行讀取核心邏輯

class MyBufferedReader extends Reader {
    private Reader r;
    public MyBufferedReader(Reader r) { this.r = r; }

    // 核心:一次讀一行,處理 \r \n 跨平台換行
    public String myReadLine() throws IOException {
        StringBuilder sb = new StringBuilder();
        int ch;
        while ((ch = r.read()) != -1) {
            if (ch == '\r') continue;           // 忽略 \r
            if (ch == '\n') return sb.toString(); // 遇到 \n 返回
            sb.append((char) ch);
        }
        return sb.length() > 0 ? sb.toString() : null;
    }

    // 必須實現的抽象方法,委託給被裝飾對象
    public int read(char[] cbuf, int off, int len) throws IOException {
        return r.read(cbuf, off, len);
    }
    public void close() throws IOException { r.close(); }
}

LineNumberReader 內置行號功能

JDK 提供 LineNumberReader 繼承 BufferedReader,自帶行號統計:

LineNumberReader lnr = new LineNumberReader(new FileReader("buf.txt"));
lnr.setLineNumber(2); // 設置起始行號
String line;
while ((line = lnr.readLine()) != null) {
    System.out.println(lnr.getLineNumber() + ":" + line);
}

輸出行號從 3 開始(設值 2 後下一行為 3)。

自定義行號裝飾器:繼承自定義緩衝類

public class MyLineNumberReader extends MyBufferedReader {
    private int lineNumber;
    public MyLineNumberReader(Reader r) { super(r); }
    public void setLineNumber(int n) { this.lineNumber = n; }
    public int getLineNumber() { return lineNumber; }

    @Override
    public String myReadLine() throws IOException {
        lineNumber++;
        return super.myReadLine();
    }
}

測試時設置 setLineNumber(200),輸出行號從 201 遞增,完美復刻 JDK 行為。

總結

  • 裝飾模式通過「持有同類型引用」實現功能疊加,避免繼承層級膨脹。
  • IO 體系中 Reader/Writer 及其子類均採用此模式。
  • 自定義裝飾類需實現抽象方法並委託給被裝飾對象,核心增強邏輯自行實現。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved