Appearance
装饰器模式(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. 解决的问题
经典场景
- 动态功能扩展
- 图形界面组件添加边框、阴影(如
JScrollPane
装饰JTextArea
)。
- 图形界面组件添加边框、阴影(如
- IO 流处理
- Java 的
BufferedInputStream
装饰FileInputStream
添加缓冲功能。
- Java 的
- 中间件增强
- HTTP 请求处理链(如日志、鉴权装饰器)。
4. 实现注意事项
关键实现点
- 统一接口
- 装饰器和被装饰对象必须实现相同接口(如
InputStream
)。
- 装饰器和被装饰对象必须实现相同接口(如
- 嵌套支持
- 装饰器可持有其他装饰器实例(支持链式调用)。
- 透明性维护
- 避免在装饰器中暴露新增方法(否则破坏接口一致性)。
代码示例(Java IO)
java
// 基础组件:文件读取流
InputStream fileStream = new FileInputStream("data.txt");
// 装饰器1:缓冲功能
InputStream bufferedStream = new BufferedInputStream(fileStream);
// 装饰器2:解压功能
InputStream gzipStream = new GZIPInputStream(bufferedStream);
5. 实现变体
类型 | 特点 | 适用场景 |
---|---|---|
透明装饰器 | 严格遵循组件接口,不暴露新方法 | 需保持接口一致性 |
半透明装饰器 | 添加额外方法(破坏透明性,慎用) | 需要扩展接口的特殊场景 |
6. 相似模式对比
模式 | 核心区别 |
---|---|
代理模式 | 控制对象访问,装饰器增强对象功能 |
适配器模式 | 解决接口不兼容问题,装饰器保持接口一致 |
组合模式 | 处理树形结构,装饰器处理链式结构 |
7. 组合使用场景
常见搭配模式
- 工厂模式
- 场景:动态创建装饰器组合(如根据配置生成带日志和缓存的数据库连接)。
- 策略模式
- 场景:装饰器内部使用不同策略实现功能(如压缩装饰器支持 ZIP/GZIP 算法)。
- 责任链模式
- 场景:多个装饰器形成处理链(如 Web 中间件的鉴权 → 日志 → 限流)。
总结
装饰器模式是扩展对象功能的瑞士军刀,核心在于动态组合而非静态继承。其经典实现如 Java IO 流,通过嵌套装饰器实现功能叠加。使用时需注意接口透明性和过度装饰风险,合理搭配工厂模式可进一步提升灵活性。```