装饰器模式 Mermaid 类图

装饰器模式序列图

装饰器模式对象关系图

一个装饰器模式的 Java Demo。这个例子将模拟 Java I/O 中的 BufferedReader(FileReader) 结构。
装饰器模式 Java 实现
1. 首先定义组件接口
java复制代码
// 组件接口 - 定义基本操作
public interface DataReader {
String read();
void close();
}
2. 实现具体组件(被装饰的对象)
java复制代码
// 具体组件 - 文件读取器(相当于FileReader)
public class FileReader implements DataReader {
private String filename;
public FileReader(String filename) {
this.filename = filename;
System.out.println("打开文件: " + filename);
}
@Override
public String read() {
// 模拟从文件读取数据
String data = "原始文件数据 from " + filename;
System.out.println("读取文件: " + data);
return data;
}
@Override
public void close() {
System.out.println("关闭文件: " + filename);
}
}
3. 创建抽象装饰器
java复制代码
// 抽象装饰器 - 维持一个指向组件对象的引用
public abstract class DataReaderDecorator implements DataReader {
protected DataReader decoratedReader;
public DataReaderDecorator(DataReader reader) {
this.decoratedReader = reader;
}
@Override
public String read() {
return decoratedReader.read();
}
@Override
public void close() {
decoratedReader.close();
}
}
4. 实现具体装饰器
java复制代码
// 具体装饰器 - 缓冲读取器(相当于BufferedReader)
public class BufferedReader extends DataReaderDecorator {
private StringBuilder buffer;
private boolean bufferLoaded = false;
public BufferedReader(DataReader reader) {
super(reader);
this.buffer = new StringBuilder();
System.out.println("创建缓冲读取器");
}
@Override
public String read() {
if (!bufferLoaded) {
// 从被装饰的读取器读取数据并缓冲
String data = decoratedReader.read();
buffer.append("【缓冲数据】").append(data).append("【缓冲结束】");
bufferLoaded = true;
System.out.println("数据已加载到缓冲区");
}
// 从缓冲区返回数据
String result = buffer.toString();
System.out.println("从缓冲区读取: " + result);
return result;
}
// 添加装饰器特有的方法
public String readLine() {
String data = read();
return data + " (按行读取)";
}
@Override
public void close() {
buffer.setLength(0); // 清空缓冲区
bufferLoaded = false;
System.out.println("清空缓冲区");
decoratedReader.close();
}
}
5. 另一个装饰器示例 - 编码转换器
java复制代码
// 另一个具体装饰器 - 编码转换器
public class EncodingReader extends DataReaderDecorator {
private String encoding;
public EncodingReader(DataReader reader, String encoding) {
super(reader);
this.encoding = encoding;
System.out.println("创建编码转换器: " + encoding);
}
@Override
public String read() {
String originalData = decoratedReader.read();
String convertedData = "[" + encoding + "编码]" + originalData + "[/" + encoding + "]";
System.out.println("编码转换: " + convertedData);
return convertedData;
}
}
6. 客户端测试类
java复制代码
// 客户端代码 - 演示装饰器模式的使用
public class DecoratorPatternDemo {
public static void main(String[] args) {
System.out.println("=== 基础文件读取 ===");
DataReader fileReader = new FileReader("test.txt");
fileReader.read();
fileReader.close();
System.out.println("\n=== 添加缓冲功能 ===");
DataReader bufferedReader = new BufferedReader(new FileReader("test.txt"));
bufferedReader.read();
// 可以调用装饰器特有的方法
if (bufferedReader instanceof BufferedReader) {
String line = ((BufferedReader) bufferedReader).readLine();
System.out.println("特有方法调用: " + line);
}
bufferedReader.read(); // 第二次读取会使用缓冲区
bufferedReader.close();
System.out.println("\n=== 多层装饰 ===");
DataReader advancedReader = new EncodingReader(
new BufferedReader(
new FileReader("data.txt")
), "UTF-8"
);
advancedReader.read();
advancedReader.close();
System.out.println("\n=== 灵活组合 ===");
DataReader customReader = new BufferedReader(
new EncodingReader(
new FileReader("custom.txt"), "ASCII"
)
);
customReader.read();
customReader.close();
}
}
运行结果
复制代码
=== 基础文件读取 ===
打开文件: test.txt
读取文件: 原始文件数据 from test.txt
关闭文件: test.txt
=== 添加缓冲功能 ===
打开文件: test.txt
创建缓冲读取器
读取文件: 原始文件数据 from test.txt
数据已加载到缓冲区
从缓冲区读取: 【缓冲数据】原始文件数据 from test.txt【缓冲结束】
特有方法调用: 【缓冲数据】原始文件数据 from test.txt【缓冲结束】 (按行读取)
从缓冲区读取: 【缓冲数据】原始文件数据 from test.txt【缓冲结束】
清空缓冲区
关闭文件: test.txt
=== 多层装饰 ===
打开文件: data.txt
创建缓冲读取器
创建编码转换器: UTF-8
读取文件: 原始文件数据 from data.txt
数据已加载到缓冲区
从缓冲区读取: 【缓冲数据】原始文件数据 from data.txt【缓冲结束】
编码转换: [UTF-8编码]【缓冲数据】原始文件数据 from data.txt【缓冲结束】[/UTF-8]
清空缓冲区
关闭文件: data.txt
=== 灵活组合 ===
打开文件: custom.txt
创建编码转换器: ASCII
创建缓冲读取器
读取文件: 原始文件数据 from custom.txt
编码转换: [ASCII编码]原始文件数据 from custom.txt[/ASCII]
数据已加载到缓冲区
从缓冲区读取: 【缓冲数据】[ASCII编码]原始文件数据 from custom.txt[/ASCII]【缓冲结束】
清空缓冲区
关闭文件: custom.txt
模式要点总结
- 组件接口 (
DataReader): 定义核心功能 - 具体组件 (
FileReader): 实现基本功能 - 抽象装饰器 (
DataReaderDecorator): 维持组件引用,实现相同接口 - 具体装饰器 (
BufferedReader,EncodingReader): 添加额外功能
装饰器模式的优点:
- 比继承更灵活,可以动态组合功能
- 符合开闭原则,无需修改原有代码
- 可以嵌套多个装饰器
这个例子完美展示了装饰器模式如何"动态地给对象添加额外职责",正如 Java I/O 库的设计理念。