Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

  • Java IO

    • Java IO概述
    • IO基础

      • IO流体系
      • 字节流
      • 字符流
      • 字节流与字符流的转换
      • 装饰器模式与IO设计
        • 1. 什么是装饰器模式
        • 2. IO 中的包装结构
        • 3. 为什么不设计成一个大而全的类
        • 4. 常见装饰器
        • 5. 组合顺序很重要
        • 6. 关闭外层流即可吗
        • 7. 装饰器模式带来的代价
        • 专家实践清单
        • Tips 快问快答
        • 8. 总结
    • 常用IO流

    • 文件与目录操作

    • Java NIO

    • 高级主题

    • 实践与性能优化

    • 面试与设计题

    • IO实践速查

  • JVM

目录

装饰器模式与IO设计

Java IO 类非常多,初学者很容易觉得混乱。但从设计模式角度看,Java IO 的核心结构并不复杂:大量 IO 类都是通过装饰器模式组合出来的。

# 1. 什么是装饰器模式

装饰器模式用于在不修改原始对象的前提下,动态增强对象能力。

在 Java IO 中:

  • 节点流负责连接真实资源。
  • 处理流负责包装节点流并增加能力。
InputStream input = new BufferedInputStream(new FileInputStream("data.bin"));

FileInputStream 能读文件,BufferedInputStream 增加缓冲能力。两者都属于 InputStream,所以可以透明替换。

# 2. IO 中的包装结构

一个典型的 IO 组合如下:

try (DataInputStream input = new DataInputStream(
        new BufferedInputStream(
                new FileInputStream("data.bin")))) {

    int value = input.readInt();
}

从内到外看:

  1. FileInputStream:连接文件。
  2. BufferedInputStream:增加缓冲。
  3. DataInputStream:增加读取基本数据类型的能力。

每一层只关心自己的职责,这就是装饰器模式的价值。

# 3. 为什么不设计成一个大而全的类

如果 Java 设计一个 SuperFileInputStream,同时支持文件读取、缓冲、对象、基本类型、编码转换,会带来几个问题:

  • 类会变得极其庞大。
  • 很多场景只需要其中一小部分能力。
  • 能力组合不灵活。
  • 扩展新能力时容易影响旧逻辑。

装饰器模式把能力拆成小组件,需要什么就组合什么。

# 4. 常见装饰器

字节流中常见的处理流:

  • BufferedInputStream:增加缓冲。
  • DataInputStream:读取基本数据类型。
  • ObjectInputStream:读取对象。
  • PushbackInputStream:支持回退读取。
  • DigestInputStream:读取时计算摘要。

字符流中常见的处理流:

  • BufferedReader:增加缓冲和按行读取。
  • LineNumberReader:增加行号能力。
  • PushbackReader:支持字符回退。
  • PrintWriter:增加格式化输出能力。

# 5. 组合顺序很重要

流的包装顺序会影响能力和性能。

推荐:

new DataInputStream(new BufferedInputStream(new FileInputStream("data.bin")));

不推荐:

new BufferedInputStream(new DataInputStream(new FileInputStream("data.bin")));

前者先缓冲原始文件读取,再在缓冲后的流上解析基本类型,语义更自然。后者虽然某些情况下也能工作,但不符合常见组合习惯。

字符流也是类似:

new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

先把字节解码为字符,再对字符读取做缓冲和按行处理。

# 6. 关闭外层流即可吗

通常关闭最外层处理流即可。处理流的 close() 会继续关闭它包装的底层流。

try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(new FileInputStream("demo.txt"), StandardCharsets.UTF_8))) {
    // use reader
}

这里不需要单独关闭 FileInputStream,因为 reader.close() 会沿着包装链关闭底层资源。

不过如果多个处理流共享同一个底层流,就需要特别小心,避免某个包装对象提前关闭底层资源。

# 7. 装饰器模式带来的代价

装饰器模式灵活,但也有代价:

  • 类数量多,初学者学习成本高。
  • 包装层级深,代码可读性下降。
  • 错误组合可能导致语义不清。
  • 某些处理流有自己的缓冲,叠加不当可能浪费内存。

现代 Java 的 Files 工具类在常见场景中减少了显式包装,让代码更简单。

# 专家实践清单

设计点 IO 中的体现 工程启发
职责拆分 节点流连接资源,处理流增强能力 单个类不要承担所有职责
组合优先 多层包装组合能力 通过组合扩展行为
面向抽象 构造器接收父类流 业务代码依赖稳定抽象
透明增强 缓冲、转换、数据读写叠加 增强不改变底层资源语义

典型包装结构:

FileInputStream
  ▼
BufferedInputStream
  ▼
DataInputStream
  ▼
业务读取 int/long/String

# Tips 快问快答

Q:Java IO 为什么适合用装饰器模式解释? A:因为很多处理流都包装另一个流,在不改变底层资源的前提下增强能力。

Q:节点流相当于装饰器里的什么? A:相当于被装饰对象,负责连接真实数据源或目标。

Q:处理流相当于什么? A:相当于装饰器,负责增加缓冲、转换、对象读写等能力。

Q:为什么不用一个大而全的 IO 类? A:职责过多会导致类膨胀,组合式设计更灵活。

Q:包装顺序重要吗? A:重要。不同顺序会影响语义,例如先转换再缓冲和先缓冲再转换的边界不同。

Q:装饰器模式有什么代价? A:层次多时可读性下降,异常栈和资源关闭链路也更复杂。

Q:为什么关闭最外层流通常够了? A:处理流关闭时会向内传递关闭动作,最终关闭底层节点流。

Q:现代 Files API 是否取代了装饰器思想? A:没有。它只是把常见组合封装成便捷方法,底层思想仍然存在。

# 8. 总结

Java IO 的设计精髓是用装饰器模式拆分能力,再通过组合满足不同场景。理解这一点后,FileInputStream、BufferedInputStream、DataInputStream 这些类就不是孤立 API,而是一组可插拔的能力组件。

上次更新: 2026/06/25, 14:19:18
字节流与字符流的转换
文件流

← 字节流与字符流的转换 文件流→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式