文章目录
-
- [1. 引言:继承真的能解决扩展问题吗?](#1. 引言:继承真的能解决扩展问题吗?)
- [2. 什么是装饰者模式](#2. 什么是装饰者模式)
-
- [GoF 定义](#GoF 定义)
- [3. 装饰者模式的核心思想](#3. 装饰者模式的核心思想)
- [4. 装饰者模式的角色组成](#4. 装饰者模式的角色组成)
- [5. 示例场景:咖啡加料系统](#5. 示例场景:咖啡加料系统)
- [6. 装饰顺序的重要⭐](#6. 装饰顺序的重要⭐)
- [7. 装饰者模式的优点](#7. 装饰者模式的优点)
- [8. 装饰者模式的缺点](#8. 装饰者模式的缺点)
- [9. 装饰者 vs 代理 vs 适配器](#9. 装饰者 vs 代理 vs 适配器)
- [10. JDK 中的装饰者模式](#10. JDK 中的装饰者模式)
-
- [Java IO 体系](#Java IO 体系)
- [11. 适用场景](#11. 适用场景)
- [12. 一个常见误区](#12. 一个常见误区)
- 参考

1. 引言:继承真的能解决扩展问题吗?
假设我们有一个简单的咖啡类:
java
class Coffee {
double cost() {
return 10;
}
}
如果现在要支持:
- 加牛奶
- 加糖
- 加奶泡
- 任意组合
你可能会想到继承:
- MilkCoffee
- SugarCoffee
- MilkSugarCoffee
- MilkSugarFoamCoffee ...
问题很快就出现了:
- 类数量爆炸
- 组合不灵活
- 扩展困难
当继承开始失控时,就该考虑装饰者模式了。
装饰者模式解决的核心问题是:
如何在不修改原类的前提下,灵活地为对象增加功能。
2. 什么是装饰者模式
GoF 定义
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。
在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
一句话理解:
装饰者模式 = 用"组合"代替"继承"来扩展功能。
3. 装饰者模式的核心思想
装饰者模式的本质在于:
- 不修改原有类
- 不通过继承增加功能
- 在运行期动态叠加功能
核心原则:
对扩展开放,对修改关闭。
4. 装饰者模式的角色组成
装饰者模式通常包含四个角色:
- 抽象组件(Component)
定义一个抽象接口以规范准备接收附加责任的对象。
- 具体组件(ConcreteComponent)
实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰者(Decorator)
继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰者(ConcreteDecorator)
实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
5. 示例场景:咖啡加料系统
5.1 抽象组件
java
public interface Beverage {
double cost();
String getDescription();
}
5.2 具体组件
java
public class Coffee implements Beverage {
@Override
public double cost() {
return 10;
}
@Override
public String getDescription() {
return "咖啡";
}
}
5.3 抽象装饰者
java
// 注意:这里没有实现cost()方法和getDescription()方法,所以必须是抽象类
public abstract class BeverageDecorator implements Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
protected Beverage beverage; 注意这里,如果没明白可以理解为Beverage beverage=new MilkDecorator();多态实现的形式
5.4 具体装饰者
牛奶装饰者
java
public class MilkDecorator extends BeverageDecorator {
public MilkDecorator(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 2;
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 牛奶";
}
}
糖装饰者
java
public class SugarDecorator extends BeverageDecorator {
public SugarDecorator(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 1;
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 糖";
}
}
5.5 客户端使用
java
Beverage beverage = new Coffee();
beverage = new MilkDecorator(beverage);
beverage = new SugarDecorator(beverage);
System.out.println(beverage.getDescription());
System.out.println(beverage.cost());
输出结果:

6. 装饰顺序的重要⭐
java
beverage = new SugarDecorator(new MilkDecorator(new Coffee()));
- 装饰顺序不同
- 行为和结果可能不同
装饰者模式支持功能的"叠加"和"组合"。
7. 装饰者模式的优点
- 避免类爆炸
- 功能扩展灵活
- 支持运行期动态组合
- 符合开闭原则
- 比继承更灵活
8. 装饰者模式的缺点
- 类数量增加
- 调试困难
- 调用链变长
- 结构理解成本较高
9. 装饰者 vs 代理 vs 适配器
| 模式 | 核心目的 |
|---|---|
| 装饰者 | 动态扩展功能 |
| 代理 | 控制访问 |
| 适配器 | 接口转换 |
结构相似,意图不同。
10. JDK 中的装饰者模式
Java IO 体系
java
InputStream in =
new BufferedInputStream(
new DataInputStream(
new FileInputStream("test.txt")
)
);
FileInputStream:基础功能BufferedInputStream:缓存DataInputStream:数据解析
👉 经典装饰者模式示例
11. 适用场景
适合使用
- 功能可以自由组合
- 扩展方式多样
- 不希望使用继承
- 框架、基础组件设计
不适合使用
- 功能极其简单
- 扩展点非常少
- 对性能极端敏感
12. 一个常见误区
装饰者模式不是"为了多写几层包装",而是为了"组合能力"。