Skip to content

装饰器模式(Decorator Pattern)

1. 官方定义

"Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality."
—— 《Design Patterns: Elements of Reusable Object-Oriented Software》(GoF, 1994)

核心:动态地为对象添加额外职责,且比继承更灵活。


2. 模式解释

核心思想

  • 组合优于继承:通过包装(Wrapper)扩展对象功能,而非通过子类继承。
  • 透明性:装饰器与被装饰对象实现同一接口,客户端无感知。
  • 动态叠加:可嵌套多个装饰器(如 BufferedInputStream 包装 FileInputStream)。

典型结构

plaintext
          |<<Interface>>|
          Component

              | implements
      ┌───────┴───────┐
      |               |
ConcreteComponent   Decorator

                        | holds a Component
                        |
                ConcreteDecoratorA

优点

  • 开闭原则:扩展功能无需修改原有类。
  • 灵活性:运行时动态组合功能(如咖啡加糖、加奶)。
  • 避免类爆炸:替代多层次的继承结构。

缺点

  • 复杂性:多层装饰可能导致代码可读性下降。
  • 接口一致性风险:装饰器必须严格遵循组件接口。

3. 解决的问题

经典场景

  1. 动态功能扩展
    • 图形界面组件添加边框、阴影(如 JScrollPane 装饰 JTextArea)。
  2. IO 流处理
    • Java 的 BufferedInputStream 装饰 FileInputStream 添加缓冲功能。
  3. 中间件增强
    • HTTP 请求处理链(如日志、鉴权装饰器)。

4. 实现注意事项

关键实现点

  1. 统一接口
    • 装饰器和被装饰对象必须实现相同接口(如 InputStream)。
  2. 嵌套支持
    • 装饰器可持有其他装饰器实例(支持链式调用)。
  3. 透明性维护
    • 避免在装饰器中暴露新增方法(否则破坏接口一致性)。

代码示例(Java IO)

java
// 基础组件:文件读取流
InputStream fileStream = new FileInputStream("data.txt");

// 装饰器1:缓冲功能
InputStream bufferedStream = new BufferedInputStream(fileStream);

// 装饰器2:解压功能
InputStream gzipStream = new GZIPInputStream(bufferedStream);

5. 实现变体

类型特点适用场景
透明装饰器严格遵循组件接口,不暴露新方法需保持接口一致性
半透明装饰器添加额外方法(破坏透明性,慎用)需要扩展接口的特殊场景

6. 相似模式对比

模式核心区别
代理模式控制对象访问,装饰器增强对象功能
适配器模式解决接口不兼容问题,装饰器保持接口一致
组合模式处理树形结构,装饰器处理链式结构

7. 组合使用场景

常见搭配模式

  1. 工厂模式
    • 场景:动态创建装饰器组合(如根据配置生成带日志和缓存的数据库连接)。
  2. 策略模式
    • 场景:装饰器内部使用不同策略实现功能(如压缩装饰器支持 ZIP/GZIP 算法)。
  3. 责任链模式
    • 场景:多个装饰器形成处理链(如 Web 中间件的鉴权 → 日志 → 限流)。

总结
装饰器模式是扩展对象功能的瑞士军刀,核心在于动态组合而非静态继承。其经典实现如 Java IO 流,通过嵌套装饰器实现功能叠加。使用时需注意接口透明性和过度装饰风险,合理搭配工厂模式可进一步提升灵活性。```