装饰器模式是什么
装饰器在不改变接口的前提下为对象叠加行为:层层包装,每层只做一件事,例如缓冲、压缩、加密、缓存。相比继承,叠加方式在运行期决定,组合数量不受类层次限制。判断是否适用,看这层职责是否需要在不同组合下复用。
基本信息
| 意图 | 动态叠加职责,接口保持不变 |
|---|---|
| 形态 | 实现同一接口,内部持有被装饰对象 |
| 典型实例 | 输入输出流管道、HTTP 中间件链 |
| 关键性质 | 包装顺序即执行顺序 |
| 与代理的区别 | 装饰器关注叠加职责,代理关注访问控制 |
典型使用场景
- 流处理叠加缓冲、压缩与加密
- HTTP 中间件链添加鉴权、日志与限流
- 缓存层包裹数据访问对象
- 指标采集包裹调用入口
- 按配置组合横切能力
Java 流管道
Java 流管道
InputStream in = new BufferedInputStream(
new GZIPInputStream(
new FileInputStream(path)));
// 读取顺序:先解压,再经过缓冲层
// 包装顺序反过来写,行为与性能都会不同与相邻模式的差别
| 模式 | 目的 | 差别 |
|---|---|---|
| 装饰器 | 叠加职责 | 接口不变,可多层包装 |
| 代理 | 控制访问 | 通常一对一,关注权限或延迟加载 |
| 适配器 | 转换接口 | 改变对外的接口形状 |
中间件与装饰链的执行顺序就是包装顺序:排查问题时先确认层序,再看每层做了什么,通常比逐层加日志更快。
落地要点
- 每层只做一件事,职责单一时才好自由组合
- 对外接口保持一致,调用方无需知道包装了几层
- 组合顺序配置化,并在文档或注释里写清实际顺序
- 为关键层加指标,便于定位是哪一层拖慢了调用
- 固定搭配的几层可以合并成语义明确的组件
层数过多会让一次调用穿过十几层:调试时栈很深、性能也有开销。固定搭配的层可以合并,组合方式要保持可读。
测试装饰链时优先测组合后的行为:既验证每层自身,也验证顺序正确,例如先压缩后加密与先加密后压缩的结果完全不同。