装饰器模式
装饰器模式,可以在不修改对象外观和功能的情况下添加或者删除对象功能。它可以使用一种对客户端来说是透明的方法来修改对象的功能,也就是使用初始类的子类实例对初始对象进行授权。 装饰器模式来为对象动态地添加了额外的责任,这样就在不使用静态继承的情况下,为修改对象功能提供了灵活的选择。

主要角色
抽象构件(Component): 这是一个接口或抽象类,它定义了被装饰对象的接口。客户端通常通过这个接口与具体的实现类交互。
具体构件(ConcreteComponent): 实现了抽象构件接口的具体对象,它是原始对象,具有核心业务功能。装饰器可以用于增强或修改具体构件的行为。
抽象装饰(Decorator): 继承自抽象构件,实现了抽象构件的所有方法,并且包含一个指向抽象构件类型的引用,这样就可以在内部持有一个具体构件实例。 抽象装饰为具体装饰器提供了一个统一的接口扩展点,允许在运行时动态地向具体构件添加新的职责或行为。
具体装饰(ConcreteDecorator): 是抽象装饰类的子类,除了重写并实现抽象装饰中的方法外,还可以在其基础上增加额外的功能。 具体装饰器可以在调用其持有的具体构件的方法时,先执行自己的附加操作,然后将控制权传递给被装饰的对象,从而达到在不修改原有类的基础上动态扩展功能的目的。
代码实现
抽象构件
public abstract class Component {
public abstract void operation();
}具体构件
具体构件是抽象构件的实现,它里面的实现是最原始的逻辑。
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("Concrete component operation");
}
}抽象装饰器
写抽象装饰器,需要注意两个地方:
- 需要聚合原始构件。(以便进行行为扩展)
- 需要继承抽象构件。(装饰器首先是抽象构件的子类,这样行为才是一直的。只是它的实现可以是另外一种子构件,也可以是扩展其持有的子构件的行为)
public abstract class Decorator extends Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
}具体装饰器
具体装饰器,由于持有具体构件的对象,并且它也是抽象构件的子类,因此一方面它可以扩展具体构件的功能,另一方面也可以重写具体构件。
ConcreteDecoratorA是一个扩展的例子。
public class ConcreteDecoratorA extends Decorator {
private String addedState;
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
this.addedState = "added";
Component component = super.getComponent();
if (component != null) {
component.operation();
}
System.out.println("state added");
}
}ConcreteDecoratorB是一个重写的例子。
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
this.addedBehavior();
}
public void addedBehavior() {
System.out.println("Added behavior B");
}
}调用
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
Decorator decoratorA = new ConcreteDecoratorA(component);
Decorator decoratorB = new ConcreteDecoratorB(component);
component.operation();
System.out.println("========");
decoratorA.operation();
System.out.println("========");
decoratorB.operation();
}
}结果如下:

与其他设计模式的对比
| 设计模式 | 主要功能 | 实现方式 | 适用场景 |
|---|---|---|---|
| 装饰器模式 | 动态扩展对象功能 | 组合 + 继承 | 需要动态添加/删除功能时 |
| 适配器模式 | 接口转换 | 继承或组合 | 接口不兼容时 |
| 代理模式 | 控制对象访问 | 组合 | 需要控制访问权限时 |
| 策略模式 | 算法替换 | 组合 | 算法需要频繁切换时 |
总结
核心思想
装饰器模式通过组合而非继承的方式,动态地给对象添加额外的责任(功能),同时保持类的单一职责原则。它允许在不修改原始类结构的情况下,灵活地扩展对象的功能。
主要角色
- 抽象构件(Component):定义被装饰对象的接口
- 具体构件(ConcreteComponent):实现抽象构件的具体对象,是原始功能的提供者
- 抽象装饰(Decorator):继承抽象构件并持有一个抽象构件引用
- 具体装饰(ConcreteDecorator):实现抽象装饰,添加具体的额外功能
实现方式
- 使用组合来实现对被装饰对象的引用
- 使用继承来保持与被装饰对象的接口一致性
- 支持多层装饰,可以为对象添加多个功能
优点
- 灵活性:可以动态地添加/删除功能,比继承更灵活
- 单一职责:每个装饰器只负责一个额外功能
- 可组合性:多个装饰器可以组合使用,实现复杂功能
- 开闭原则:对扩展开放,对修改关闭
缺点
- 复杂性增加:过多的装饰器会导致类的数量增加
- 调试困难:多层装饰可能导致调试时难以追踪调用路径
适用场景
- 当需要动态地为对象添加/删除功能时
- 当使用继承会导致类数量爆炸时
- 当需要保持类的单一职责原则时
- 当需要组合多个功能时
实际应用
- Java I/O类库中的流包装器(如BufferedInputStream、DataInputStream)
- Spring框架中的AOP(面向切面编程)
- JavaScript中的高阶函数和装饰器
- Python中的装饰器语法