软件设计模式-装饰器模式

装饰器模式 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

模式要点总结

  1. 组件接口 (DataReader): 定义核心功能
  2. 具体组件 (FileReader): 实现基本功能
  3. 抽象装饰器 (DataReaderDecorator): 维持组件引用,实现相同接口
  4. 具体装饰器 (BufferedReader, EncodingReader): 添加额外功能

装饰器模式的优点:

  • 比继承更灵活,可以动态组合功能
  • 符合开闭原则,无需修改原有代码
  • 可以嵌套多个装饰器

这个例子完美展示了装饰器模式如何"动态地给对象添加额外职责",正如 Java I/O 库的设计理念。

相关推荐
AI数据皮皮侠7 分钟前
中国乡村旅游重点村镇数据
大数据·人工智能·python·深度学习·机器学习
小北方城市网15 分钟前
第 11 课:Python 全栈项目进阶与职业发展指南|从项目到职场的无缝衔接(课程终章・进阶篇)
大数据·开发语言·人工智能·python·数据库架构·geo
danyang_Q21 分钟前
d2l安装(miniforge+cuda+pytorch)
人工智能·pytorch·python
JavaBoy_XJ38 分钟前
行为型-模板模式
设计模式·模板方法模式·模板模式
源码梦想家1 小时前
多语言高性能异步任务队列与实时监控实践:Python、Java、Go、C++实战解析
开发语言·python
百***78751 小时前
Gemini 3.0 Pro与2.5深度对比:技术升级与开发实战指南
开发语言·python·gpt
reasonsummer1 小时前
【教学类-122-01】20260105“折纸-东南西北中”(4个方向文字,9个小图案)
python·通义万相
智航GIS1 小时前
9.6 JSON 基本操作
python·json
@zulnger2 小时前
python 学习笔记(文件读写)
笔记·python·学习
weixin_462446232 小时前
Python 使用 Tkinter + openpyxl 处理 Excel 文件并显示实时进度条
python·excel·tkinter