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

装饰器模式 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 库的设计理念。

相关推荐
J_liaty9 分钟前
23种设计模式一代理模式
设计模式·代理模式
历程里程碑1 小时前
普通数组----合并区间
java·数据结构·python·算法·leetcode·职场和发展·tornado
weixin_395448911 小时前
mult_yolov5_post_copy.c_cursor_0205
c语言·python·yolo
执风挽^1 小时前
Python基础编程题2
开发语言·python·算法·visual studio code
纤纡.1 小时前
PyTorch 入门精讲:从框架选择到 MNIST 手写数字识别实战
人工智能·pytorch·python
kjkdd2 小时前
6.1 核心组件(Agent)
python·ai·语言模型·langchain·ai编程
小镇敲码人2 小时前
剖析CANN框架中Samples仓库:从示例到实战的AI开发指南
c++·人工智能·python·华为·acl·cann
萧鼎2 小时前
Python 包管理的“超音速”革命:全面上手 uv 工具链
开发语言·python·uv
alvin_20052 小时前
python之OpenGL应用(二)Hello Triangle
python·opengl
铁蛋AI编程实战3 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python