外观
一句话答案
动态给对象添加职责比继承更灵活,Java IO 流(BufferedReader 装饰 InputStreamReader)是典型应用。
核心要点
装饰器模式在不改变原始对象结构的情况下,动态地给对象添加新功能。装饰器和被装饰者实现相同的接口/继承相同的抽象类,装饰器内部持有被装饰对象的引用。
核心结构:
Component(抽象组件)
├── ConcreteComponent(被装饰的具体对象)
└── Decorator(装饰器抽象类,持有 Component 引用)
├── ConcreteDecoratorA
└── ConcreteDecoratorB装饰器 vs 继承:
| 维度 | 装饰器模式 | 继承 |
|---|---|---|
| 扩展方式 | 运行时动态组合 | 编译期静态确定 |
| 灵活性 | 可自由搭配多个装饰器 | 类爆炸(每种组合一个子类) |
| 开闭原则 | 遵守(新增装饰器即可) | 可能违反 |
Java IO 中的装饰器模式:
Java IO 是装饰器模式最经典的应用。InputStream 是抽象组件,FileInputStream 是具体组件,各种 FilterInputStream 子类是装饰器:
InputStream(抽象组件)
├── FileInputStream(具体组件:读文件)
├── ByteArrayInputStream(具体组件:读字节数组)
└── FilterInputStream(装饰器基类)
├── BufferedInputStream(增加缓冲功能)
├── DataInputStream(增加读取基本类型功能)
└── PushbackInputStream(增加回退功能)java
// 装饰器的层层包装——给 FileInputStream 添加缓冲 + 数据类型读取能力
InputStream is = new DataInputStream(
new BufferedInputStream(
new FileInputStream("data.bin")
)
);
// FileInputStream: 负责从文件读取原始字节
// BufferedInputStream: 装饰器,增加了缓冲区(默认 8KB)减少磁盘 IO
// DataInputStream: 装饰器,增加了 readInt()/readDouble() 等方法关键区分——装饰器 vs 代理:
- 装饰器:增强功能,不改变接口语义(BufferedInputStream 加了缓冲但还是 InputStream)
- 代理:控制访问,可能加权限检查、远程调用等(AOP 代理控制方法调用)
追问与易错
追问方向:
- Java IO 中怎么体现?
- 和继承比优势?
- 和代理关键区别?
易错点:
- ❌ 装饰器和代理一样——意图不同增强 vs 控制
- ❌ 装饰器只能嵌套一层——可以多层
💡 记忆锚点
煎饼摊加料:基础煎饼(FileInputStream)加一层鸡蛋(BufferedInputStream加缓冲)再加一层肠(DataInputStream加类型读取),层层包裹但本质还是煎饼(InputStream),比继承灵活——继承等于把所有配料焊死在一种煎饼上。