概述
装饰器模式是结构型模式,其核心意图是:在不修改原始对象的基础上,动态地添加新行为,而且仅影响被装饰的对象,不影响同类其他实例 。这种模式避免了继承导致的类爆炸问题,同时符合开闭原则(对扩展开放,对修改关闭)。
模式结构
整体结构分为四大角色:
角色 | 说明 |
---|---|
Component | 核心接口/抽象类,定义可装饰交互 operation() |
ConcreteComponent | 具体组件,提供默认行为实现 |
Decorator | 抽象装饰器,实现 Component 接口,包含对 Component 的引用,并在内部调用其方法 |
ConcreteDecorator | 具体装饰器,继承 Decorator,实现前置或后置增强逻辑 |
UML 图示可见上方图片中 Component、ConcreteComponent、Decorator、ConcreteDecorator 的层次结构。
代码样例
// Component 接口
public interface Coffee {
String getDescription();
double getCost();
}
// ConcreteComponent
public class PlainCoffee implements Coffee {
@Override public String getDescription() { return "Plain Coffee"; }
@Override public double getCost() { return 2.0; }
}
// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {
protected final Coffee decorated;
public CoffeeDecorator(Coffee decorated) { this.decorated = decorated; }
@Override public String getDescription() { return decorated.getDescription(); }
@Override public double getCost() { return decorated.getCost(); }
}
// 多个具体装饰器
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee c) { super(c); }
@Override public String getDescription() { return super.getDescription() + ", Milk"; }
@Override public double getCost() { return super.getCost() + 0.5; }
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee c) { super(c); }
@Override public String getDescription() { return super.getDescription() + ", Sugar"; }
@Override public double getCost() { return super.getCost() + 0.2; }
}
客户端构造示例:
Coffee coffee = new SugarDecorator(new MilkDecorator(new PlainCoffee()));
System.out.println(coffee.getDescription()); // Plain Coffee, Milk, Sugar
System.out.println(coffee.getCost()); // 2.7
详细示例说明请参见 GeeksforGeeks 和 DigitalOcean 教程 ([geeksforgeeks.org][3])。
调用说明
- 客户端通过
new
创建基础对象(ConcreteComponent)。 - 可链式包装多个 Decorator。
- 每次调用
operation() (getDescription() and getCost())
,都会调用当前装饰器的方法,先执行增强逻辑,再委派给被装饰对象,形成调用栈。
流程例如:
ConcreteDecorator2.getDescription()
→
增强逻辑 →
ConcreteDecorator1.getDescription()
→
增强 →
ConcreteComponent.getDescription()
。
ConcreteDecorator2.getCost()
→
增强逻辑 →
ConcreteDecorator1.getCost()
→
增强 →
ConcreteComponent.getCost()
。
应用场景
- 1.Java I/O流体系
通过装饰器模式实现流的缓冲、数据转换等功能。
InputStream为抽象组件,FileInputStream为具体组件。
BufferedInputStream、DataInputStream等作为装饰器,逐层扩展功能。 - 2.GUI组件增强
为窗口动态添加滚动条、边框等装饰,而无需修改原有组件类。
如Swing中的JScrollPane装饰JPanel,动态添加滚动条功能。 - 3.Web请求处理
通过装饰器实现日志记录、权限校验等横向功能扩展。 - 4.动态功能扩展
如咖啡订单系统中动态添加配料,无需修改原有类。
优势与适用性分析
优势
- 增强可组合性:行为可在运行时任意组合;
- 遵循开闭原则:无需修改原始代码,易扩展;
- 结构清晰,职责单一,每个装饰器聚焦一种功能。
缺点
- 装饰链深了可能难以理解调试;
- 对性能有轻微影响(多层对象调用开销);
- 过度使用可能让系统变得复杂。
总结
装饰器模式通过将功能封装到多个小 decorator 中并按需动态组合,使得行为扩展既灵活又安全,是结构型设计的重要工具,适合于功能模块多变、扩展性要求高的场景,你学到了么?