Java IO包中哪些设计模式应用详解?

摘要:Java IO包(java.io)是设计模式应用的经典案例,其核心类库通过多种设计模式解决了“不同数据源数据类型的读写”“功能扩展”“资源管理”等核心问题。下面我会逐一拆解IO包中用到的核心设计模式,结合源码示例和使用场景讲清楚每个模式的
Java IO包(java.io)是设计模式应用的经典案例,其核心类库通过多种设计模式解决了“不同数据源/数据类型的读写”“功能扩展”“资源管理”等核心问题。下面我会逐一拆解IO包中用到的核心设计模式,结合源码示例和使用场景讲清楚每个模式的应用方式。 一、装饰器模式(Decorator Pattern) 核心作用 动态地给一个对象添加额外的功能,且不改变其原有结构,是继承的灵活替代方案。 IO包中的应用场景 IO包中字节流/字符流的功能扩展完全基于装饰器模式实现: 抽象组件(Component):InputStream/OutputStream(字节流)、Reader/Writer(字符流)——定义了IO操作的核心接口; 具体组件(ConcreteComponent):FileInputStream/FileOutputStream、FileReader/FileWriter——基础的数据源实现(直接操作文件); 装饰器抽象类(Decorator):FilterInputStream/FilterOutputStream、FilterReader/FilterWriter——继承自核心组件,持有一个核心组件的引用; 具体装饰器(ConcreteDecorator):BufferedInputStream(缓冲)、DataInputStream(基本类型读写)、InputStreamReader(字节转字符)——给基础流添加额外功能。 代码示例(装饰器模式核心体现) import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class DecoratorPatternDemo { public static void main(String[] args) { // 1. 基础组件:FileInputStream(直接读文件,无缓冲) try (InputStream fileIn = new FileInputStream("test.txt"); // 2. 装饰器:BufferedInputStream(给基础流添加缓冲功能) InputStream bufferedIn = new BufferedInputStream(fileIn); // 可叠加多个装饰器:比如再套DataInputStream(添加基本类型读写) // DataInputStream dataIn = new DataInputStream(bufferedIn); ) { int data; // 缓冲流通过预读数据减少磁盘IO,功能扩展但不改变InputStream接口 while ((data = bufferedIn.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } } } 关键特点 装饰器和被装饰者实现同一个接口(如都继承InputStream),对外暴露统一API; 可叠加多个装饰器(如BufferedInputStream + DataInputStream),灵活组合功能; 无需修改原有类代码,符合“开闭原则”。 二、适配器模式(Adapter Pattern) 核心作用 将一个类的接口转换成客户期望的另一个接口,解决接口不兼容的问题。 IO包中的应用场景 最典型的是字节流与字符流的适配: 字节流(InputStream/OutputStream):处理二进制数据; 字符流(Reader/Writer):处理文本数据(按字符编码); 适配器类:InputStreamReader(字节流→字符流)、OutputStreamWriter(字节流→字符流)。 源码核心逻辑(InputStreamReader) // InputStreamReader 实现了 Reader(字符流接口),内部持有 InputStream(字节流)和编码转换器 public class InputStreamReader extends Reader { private final StreamDecoder sd; // 核心适配器:将字节解码为字符 // 构造器:传入字节流(被适配者),适配为字符流 public InputStreamReader(InputStream in) { super(in); try { sd = StreamDecoder.forInputStreamReader(in, this, (String)null); } catch (UnsupportedEncodingException e) { throw new Error(e); } } // 重写Reader的read方法,底层调用字节流的读取+解码 public int read() throws IOException { return sd.read(); } } 使用示例 import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; public class AdapterPatternDemo { public static void main(String[] args) { // 字节流(FileInputStream)是被适配者 try (FileInputStream fis = new FileInputStream("test.txt"); // 适配器:将字节流适配为字符流(Reader) Reader reader = new InputStreamReader(fis, "UTF-8")) { int ch; // 按字符读取(适配后的接口) while ((ch = reader.read()) != -1) { System.out.print((char) ch); } } catch (IOException e) { e.printStackTrace(); } } } 三、工厂模式(Factory Pattern) 核心作用 隐藏对象创建的细节,通过统一接口创建对象,降低耦合。 IO包中的应用场景 IO包中主要用简单工厂(静态工厂),核心体现: FileChannel的创建:FileInputStream.getChannel()、FileOutputStream.getChannel(); Files工具类(NIO):Files.newBufferedReader()、Files.newBufferedWriter(); InputStream的子类创建:FileInputStream、ByteArrayInputStream等通过构造器(简化版工厂)创建。 代码示例 import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; public class FactoryPatternDemo { public static void main(String[] args) { // 静态工厂方法:Files.newBufferedReader(创建BufferedReader对象,隐藏创建细节) try (BufferedReader br = Files.newBufferedReader(Paths.get("test.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } // FileChannel的工厂方法(实例工厂) try (FileInputStream fis = new FileInputStream("test.txt")) { // getChannel() 是工厂方法,创建FileChannel实例 System.out.println(fis.getChannel().size()); } catch (IOException e) { e.printStackTrace(); } } } 四、单例模式(Singleton Pattern) 核心作用 保证一个类只有一个实例,并提供全局访问点。 IO包中的应用场景 java.io.FileDescriptor中的标准流实例(stdin/stdout/stderr)是单例: public final class FileDescriptor { // 静态单例:标准输入、输出、错误流 public static final FileDescriptor in = new FileDescriptor(0); public static final FileDescriptor out = new FileDescriptor(1); public static final FileDescriptor err = new FileDescriptor(2); private FileDescriptor(int fd) { this.fd = fd; this.handle = new Handle(fd); } // 其他代码... } 使用场景 System.in/System.out底层依赖这些单例: // System.out 底层是 PrintStream,关联 FileDescriptor.out 单例 System.out.println("Hello IO"); // System.in 关联 FileDescriptor.in 单例 System.in.read(); 五、模板方法模式(Template Method Pattern) 核心作用 定义一个算法的骨架,将步骤延迟到子类实现,保证算法结构不变。 IO包中的应用场景 Reader/Writer、InputStream/OutputStream的抽象类定义了核心方法的骨架,子类实现具体逻辑: 抽象类(模板):InputStream定义了read()(单字节读取)、read(byte[])(批量读取)的骨架; 子类(实现):FileInputStream重写read()方法,实现从文件读取字节的具体逻辑。 源码核心逻辑(InputStream) public abstract class InputStream implements Closeable { // 抽象方法(子类必须实现):核心步骤延迟到子类 public abstract int read() throws IOException; // 模板方法:定义批量读取的算法骨架,复用逻辑 public int read(byte b[]) throws IOException { return read(b, 0, b.length); } // 模板方法:批量读取的具体骨架 public int read(byte b[], int off, int len) throws IOException { // 校验逻辑(固定) if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } // 调用抽象方法read()(子类实现) int c = read(); if (c == -1) { return -1; } b[off] = (byte)c; // 循环读取(固定逻辑) int i = 1; try { for (; i < len ; i++) { c = read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; } } 子类实现(FileInputStream) public class FileInputStream extends InputStream { // 实现抽象方法read():具体的文件读取逻辑 public int read() throws IOException { return read0(); // 本地方法,实现从文件读取单字节 } // 可选重写批量读取(优化性能) public int read(byte b[], int off, int len) throws IOException { return readBytes(b, off, len); // 优化后的批量读取 } } 六、观察者模式(Observer Pattern) 核心作用 对象间一对多的依赖,当一个对象状态变化,所有依赖者都会收到通知。 IO包中的应用场景 java.io.Observer(已标记为过时,但仍是经典应用)和Observable类: 比如监控文件变化时,可通过Observable包装文件流,状态变化时通知观察者。 简化示例 import java.io.File; import java.io.IOException; import java.util.Observable; import java.util.Observer; // 被观察者:监控文件变化 class FileObservable extends Observable { private File file; private long lastModified; public FileObservable(File file) { this.file = file; this.lastModified = file.lastModified(); } public void checkChange() { long current = file.lastModified(); if (current != lastModified) { lastModified = current; setChanged(); // 标记状态变化 notifyObservers(file); // 通知观察者 } } } // 观察者:处理文件变化 class FileObserver implements Observer { @Override public void update(Observable o, Object arg) { File file = (File) arg; System.out.println("文件 " + file.getName() + " 已修改"); } } public class ObserverPatternDemo { public static void main(String[] args) throws IOException, InterruptedException { File file = new File("test.txt"); FileObservable observable = new FileObservable(file); observable.addObserver(new FileObserver()); // 模拟监控文件变化 while (true) { observable.checkChange(); Thread.sleep(1000); } } } 总结 核心模式:Java IO包最核心的是装饰器模式(流的功能扩展)和适配器模式(字节/字符流适配),几乎所有流操作都基于这两个模式; 辅助模式:工厂模式(对象创建)、模板方法模式(算法骨架)、单例模式(标准流)是补充,解决对象创建、算法复用、全局实例问题; 设计思想:所有模式都围绕“解耦”“复用”“开闭原则”设计,比如装饰器模式让流功能可灵活组合,模板方法让算法骨架统一且子类可定制。