bufferedreader 是装饰模式的典型实现:它组合 reader 而非继承,通过统一接口 reader 实现功能增强、多层嵌套与运行时自由装配。

直接用 Java IO 流中的 BufferedReader 就是最典型的接口实现装饰模式实战——它不继承 FileReader,而是持有一个 Reader 引用,通过组合方式增强读取能力,且能装饰任意 Reader 子类。
明确共同接口:以 Reader 为统一契约
装饰模式的第一步是定义所有参与者(被装饰对象、装饰器)共用的接口。Java IO 中的 Reader 抽象类就是这个角色——它声明了 read()、close() 等核心方法,所有具体流(FileReader、StringReader、InputStreamReader)都实现它。装饰器也必须实现该接口,才能被客户端无缝替换使用。
- 客户端只依赖 Reader 接口,不关心底层是文件、字符串还是网络流
- 新增装饰器只需实现 Reader,无需修改任何已有类
- 多个装饰器可嵌套(如
new BufferedReader(new InputStreamReader(...))),每层都遵守同一接口
构造时注入被装饰对象:组合而非继承
装饰器类(如 BufferedReader)在构造时接收一个 Reader 实例,并将其保存为私有字段。这不是“is-a”关系,而是“has-a”——它拥有一个 Reader,而不是变成另一个 Reader 的子类。
- 代码示意:
private final Reader in;+public BufferedReader(Reader in) { this.in = in; } - 所有方法调用最终都委托给
in,例如read()先查缓存,缓存空则调用in.read() - 这样避免了为每个 Reader 子类都写一个
BufferedXxxReader,大幅减少类爆炸
在委托前后添加增强逻辑:功能叠加清晰可控
装饰器不是简单转发,而是在调用被装饰对象方法的前、后或异常时插入新行为。比如 BufferedReader.readLine():
- 它不直接调用
in.read()一行行读,而是利用内部字符数组做缓冲,批量读取提升性能 -
readLine()内部循环调用in.read(),直到遇到\n或\r\n,再返回整行字符串 - 关闭时先清空缓冲区,再调用
in.close(),确保资源释放顺序正确 - 你也可以自定义装饰器,比如加日志:
System.out.println("即将读取..."); String line = super.readLine(); System.out.println("已读:" + line);
多层装饰自由组合:运行时按需装配
因为每层装饰器都实现相同接口,你可以像搭积木一样串联多个增强:
- 示例:
new LineNumberReader(new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"), "UTF-8"))) - 最内层负责字节→字符解码(
InputStreamReader) - 中间层提供缓冲加速(
BufferedReader) - 最外层增加行号追踪(
LineNumberReader) - 每一层只专注一件事,职责单一,可复用、可替换、可测试










