Java IO 与 装饰者模式(Decorator Pattern)
装饰者模式是 Java IO 体系的核心设计模式,它通过动态组合功能,实现了流的灵活扩展。以下是装饰者模式在 Java IO 中的深度解析:
一、装饰者模式核心概念
1. 模式定义
- 目的:动态地给对象添加额外的职责,而不改变其结构。
- 角色:
- 组件(Component):定义接口(如
InputStream
/OutputStream
)。 - 具体组件(ConcreteComponent):实现接口的类(如
FileInputStream
)。 - 装饰者(Decorator):持有组件引用并实现接口(如
FilterInputStream
)。 - 具体装饰者(ConcreteDecorator):添加具体功能(如
BufferedInputStream
)。
- 组件(Component):定义接口(如
2. 类图关系
Component
/ \
ConcreteComponent Decorator
| |
FileInputStream FilterInputStream
/ \
BufferedInputStream DataInputStream
二、Java IO 中的装饰者模式实现
1. 抽象组件(Component)
- 字节流接口:
public abstract class InputStream { public abstract int read() throws IOException; // 其他方法... }
- 字符流接口:
public abstract class Reader { public abstract int read(char[] cbuf, int off, int len) throws IOException; // 其他方法... }
2. 具体组件(ConcreteComponent)
- 节点流:直接操作数据源的类。
public class FileInputStream extends InputStream { // 直接读取文件 }
3. 抽象装饰者(Decorator)
- 字节流装饰者:
public abstract class FilterInputStream extends InputStream { protected InputStream in; // 持有组件引用 protected FilterInputStream(InputStream in) { this.in = in; } // 委托实现基础方法 public int read() throws IOException { return in.read(); } }
- 字符流装饰者:
public abstract class FilterReader extends Reader { protected Reader in; protected FilterReader(Reader in) { this.in = in; } // 委托实现基础方法 public int read(char[] cbuf, int off, int len) throws IOException { return in.read(cbuf, off, len); } }
4. 具体装饰者(ConcreteDecorator)
- 功能增强类:
// 缓冲输入流 public class BufferedInputStream extends FilterInputStream { private byte[] buf; // 缓冲区 public BufferedInputStream(InputStream in) { super(in); this.buf = new byte[8192]; // 默认8KB缓冲 } // 重写 read() 方法实现缓冲逻辑 public synchronized int read() throws IOException { if (pos >= count) { fill(); // 从底层流填充缓冲区 } return buf[pos++] & 0xFF; } } // 数据输入流(支持基本类型读写) public class DataInputStream extends FilterInputStream { public DataInputStream(InputStream in) { super(in); } // 添加 readInt(), readUTF() 等方法 public final int readInt() throws IOException { int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); // 组合为 int return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); } }
三、装饰者模式的优势
1. 动态功能组合
- 通过链式调用叠加功能:
// 组合缓冲流和数据流 DataInputStream dis = new DataInputStream( new BufferedInputStream( new FileInputStream("data.bin") ) );
2. 符合开闭原则
- 新增功能无需修改现有类(如添加
GZIPInputStream
压缩功能)。
3. 代码复用
- 共享
FilterInputStream
的基础逻辑(如错误处理)。
四、典型应用场景
1. 缓冲优化
- 问题:频繁小数据量IO性能低下。
- 解决方案:用
BufferedInputStream
/BufferedReader
减少系统调用次数。
2. 格式化读写
- 场景:读写结构化数据(如二进制协议、CSV)。
- 工具类:
DataInputStream
/DataOutputStream
:读写基本类型。PrintStream
/PrintWriter
:格式化文本输出。
3. 编码转换
- 场景:处理不同字符集(如UTF-8、GBK)。
- 工具类:
InputStreamReader isr = new InputStreamReader( new FileInputStream("file.txt"), StandardCharsets.UTF_8 );
五、装饰者模式 vs 继承
特性 | 装饰者模式 | 继承 |
---|---|---|
扩展性 | 运行时动态组合功能 | 编译时固定功能 |
代码复用 | 共享装饰者基类逻辑 | 需重复实现基础功能 |
类层次 | 扁平化,避免类爆炸 | 深层次继承树 |
典型问题 | 需谨慎处理委托链 | 脆弱的基类 |
六、总结
Java IO 通过装饰者模式实现了:
- 流的灵活扩展:动态组合缓冲、编码、格式化等功能。
- 代码复用:共享
FilterInputStream
/FilterReader
的基础逻辑。 - 符合开闭原则:新增功能无需修改现有类。
理解装饰者模式,有助于:
- 深入掌握Java IO的设计哲学。
- 在自定义流处理时,正确扩展功能而非继承。
- 识别类似设计模式(如Servlet Filter、Spring AOP)。