FilterInputStream 和 FilterOutputStream 是装饰器模式的典型实现,通过包装已有流动态增强功能(如缓冲、加密、校验等),子类重写特定方法实现定制逻辑,支持链式叠加使用。

Java 中的 FilterInputStream 和 FilterOutputStream 是装饰器模式的典型实现,用于在不修改底层流的前提下,动态增强其行为(比如缓冲、加密、压缩、校验等)。它们本身是抽象类,不能直接实例化,而是通过子类(如 BufferedInputStream、DataInputStream、CheckedInputStream 等)包装已有流来扩展功能。
理解 FilterInputStream 的装饰逻辑
FilterInputStream 构造时接收一个 InputStream 实例,所有读操作(如 read()、skip()、available())默认委托给被包装的流,子类只需重写需要增强的方法即可。例如:
-
BufferedInputStream重写了read(),内部维护缓冲区,减少底层 I/O 调用次数; -
DataInputStream在原有读取基础上,增加了readInt()、readUTF()等按 Java 基本类型解析的能力; -
CheckedInputStream在每次读取后更新校验和(如 CRC32),用于数据完整性验证。
FilterOutputStream 的装饰方式类似
FilterOutputStream 同样持有一个 OutputStream 引用,写操作(write()、flush()、close())默认转发,子类可拦截并增强。常见例子包括:
-
BufferedOutputStream缓冲写入,避免频繁系统调用; -
DataOutputStream提供writeDouble()、writeBoolean()等方法,按标准格式序列化基本类型; -
CheckedOutputStream在每次写入后更新校验和,配合CheckedInputStream可验证端到端数据一致性。
自定义 Filter 流的关键步骤
若需实现自己的过滤逻辑(如日志记录、字符编码转换、简单加解密),可继承对应抽象类:
- 继承
FilterInputStream,在构造器中传入原始流,并选择性重写read()或read(byte[])方法,在调用父类in.read(...)前后插入逻辑; - 继承
FilterOutputStream,同样传入目标流,重写write()方法,在调用out.write(...)前后处理字节(如异或加密、转码、统计字节数); - 注意:必须调用父类对应方法(即被包装流的操作),否则会中断数据流;
- 覆盖
close()时应确保调用in.close()或out.close(),避免资源泄漏。
链式装饰的实际用法
装饰器支持叠加使用,形成处理链。例如:把文件内容先缓冲、再按数据类型读取、最后校验:
InputStream fis = new FileInputStream("data.bin");
InputStream bis = new BufferedInputStream(fis);
InputStream dis = new DataInputStream(bis);
InputStream cis = new CheckedInputStream(dis, new CRC32());
写入时同理:new DataOutputStream(new BufferedOutputStream(new FileOutputStream(...)))。注意顺序——越靠近底层的装饰器越先执行(如缓冲应在数据封装之后)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











