装饰器模式
大约 2 分钟
🎨 装饰器模式(Decorator Pattern)
一句话概括:
在 不修改原类、避免继承爆炸 的前提下,
动态地为对象叠加新功能。
✨ 常见命名后缀
DecoratorWrapperEnhancer
看到这些名字,优先联想到:功能增强而非核心逻辑。
一、它解决了什么问题?
🎯 典型业务痛点
- 已有 稳定类(第三方 / 老代码)
- 想新增功能(日志、缓存、加密、校验……)
- ❌ 不能修改原类
- ❌ 继承会导致子类爆炸
🧠 传统方案的问题
| 方案 | 问题 |
|---|---|
| 直接修改原类 | 破坏稳定性、不可控 |
| 继承 | 组合一多就失控 |
| if/else | 违反开闭原则 |
👉 装饰器模式:
- 不侵入
- 可组合
- 可叠加
二、核心思想(记住这一句就够了)
装饰器和被装饰对象,必须实现同一个接口
为什么重要?
对调用方来说:
- 装饰前后 完全一致
对系统来说:
- 功能可以 像积木一样拼接
三、经典结构图
Component(抽象接口)
↑
┌─────────┴─────────┐
ConcreteComponent Decorator(抽象装饰器)
↑
┌───────────┴───────────┐
ConcreteDecoratorA ConcreteDecoratorB四、四个核心角色
| 角色 | 职责 |
|---|---|
| Component | 定义统一接口 |
| ConcreteComponent | 原始业务对象 |
| Decorator | 持有 Component,做转发 |
| ConcreteDecorator | 真正的功能增强 |
📌 装饰器 不是替代原对象,而是 包裹它。
五、最小 Java 示例
1️⃣ 统一接口
public interface DataSource {
String read();
}2️⃣ 原始实现
public class FileDataSource implements DataSource {
@Override
public String read() {
return "raw-data";
}
}3️⃣ 抽象装饰器
public abstract class DataSourceDecorator implements DataSource {
protected DataSource delegate;
public DataSourceDecorator(DataSource delegate) {
this.delegate = delegate;
}
}4️⃣ 具体装饰器
🔐 加密装饰器
public class EncryptDecorator extends DataSourceDecorator {
public EncryptDecorator(DataSource delegate) {
super(delegate);
}
@Override
public String read() {
return "encrypt(" + delegate.read() + ")";
}
}📝 日志装饰器
public class LogDecorator extends DataSourceDecorator {
public LogDecorator(DataSource delegate) {
super(delegate);
}
@Override
public String read() {
System.out.println("read start");
String data = delegate.read();
System.out.println("read end");
return data;
}
}5️⃣ 装饰顺序 = 功能顺序
DataSource ds =
new LogDecorator(
new EncryptDecorator(
new FileDataSource()
)
);
ds.read();执行链路:
Log → Encrypt → File → Encrypt → Log六、实战练习:奶茶点单系统 ☕
🎯 业务背景
- 有基础奶茶
- 可动态添加小料
- 小料任意组合
- 顺序影响描述
- ❌ 不允许继承爆炸
1️⃣ 奶茶基础能力
每杯奶茶必须包含:
- 名称
- 价格
| 基础奶茶 | 价格 |
|---|---|
| 原味奶茶 | ¥10 |
| 奶绿 | ¥12 |
2️⃣ 小料(装饰器)
| 小料 | 价格 |
|---|---|
| 珍珠 | ¥2 |
| 椰果 | ¥3 |
| 布丁 | ¥4 |
| 红豆 | ¥3 |
特点:
- 可加 0 个 / 多个
- 可重复
- 顺序不同 → 描述不同
3️⃣ 输出要求
示例 1
原味奶茶 + 珍珠 + 椰果 价格:15 元示例 2
奶绿 + 布丁 + 珍珠 + 红豆 价格:21 元💡 提示:
- 奶茶 =
Component- 小料 =
Decorator
七、真实框架中的装饰器
Spring WebSocket
WebSocketHandlerDecorator
Servlet API
HttpServletRequestWrapper
🚀 凡是 Wrapper / Decorator,几乎都在用这个思想。
🧠 总结一句话
装饰器模式 = 接口一致 + 组合嵌套 + 行为叠加
理解了这三点,
你就能在任何语言、任何框架中识别并使用它。