装饰器
更新: 6/22/2025 字数: 0 字 时长: 0 分钟
定义
装饰器模式 (Decorator Pattern) 动态地给对象添加额外职责,提供比继承更灵活的扩展方案。装饰器通过包装对象实现功能增强,同时保持接口兼容性。
角色
- 组件接口 (Component):定义被装饰对象的接口
- 具体组件 (Concrete Component):实现组件接口的基础对象
- 装饰器基类 (Decorator):实现组件接口,维护组件引用
- 具体装饰器 (Concrete Decorator):添加具体功能的装饰器实现
实现
咖啡订单系统示例
java
// 组件接口
public interface Coffee {
double cost();
String description();
}
// 具体组件
public class SimpleCoffee implements Coffee {
@Override
public double cost() {
return 10.0;
}
@Override
public String description() {
return "咖啡";
}
}
// 装饰器基类
public abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double cost() {
return decoratedCoffee.cost();
}
@Override
public String description() {
return decoratedCoffee.description();
}
}
// 具体装饰器:牛奶
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 2.0;
}
@Override
public String description() {
return super.description() + ", 牛奶";
}
}
// 具体装饰器:糖浆
public class SyrupDecorator extends CoffeeDecorator {
public SyrupDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 1.5;
}
@Override
public String description() {
return super.description() + ", 糖浆";
}
}
// 使用示例
public class CoffeeShop {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SyrupDecorator(coffee);
System.out.println(coffee.description() + " 价格:¥" + coffee.cost());
// 输出:咖啡,牛奶,糖浆 价格:¥13.5
}
}
I/O 流装饰器示例
java
// 模拟 InputStream 装饰器
public class LowerCaseInputStream extends FilterInputStream {
public LowerCaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1) ? c : Character.toLowerCase(c);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int result = super.read(b, off, len);
for (int i = off; i < off + result; i++) {
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}
// 使用示例
public class DecoratorDemo {
public static void main(String[] args) {
String text = "HELLO DECORATOR PATTERN!";
try (InputStream in = new LowerCaseInputStream(
new ByteArrayInputStream(text.getBytes()))) {
int c;
while ((c = in.read()) != -1) {
System.out.print((char)c);
}
// 输出:hello decorator pattern!
} catch (IOException e) {
e.printStackTrace();
}
}
}
优缺点
优点:
- 比继承更灵活(运行时添加/移除功能)
- 避免子类膨胀问题
- 符合开闭原则(扩展开放,修改关闭)
- 可组合多个装饰器实现复杂功能
缺点:
- 产生大量小对象增加系统复杂度
- 多层装饰增加调试难度
- 设计不当可能导致装饰链过长
- 初始化配置可能变得复杂
应用场景
- 动态透明地添加功能
- 撤销功能(通过移除装饰层)
- 扩展类功能但无法使用继承
- I/O 流处理(Java I/O 核心模式)
- GUI 组件增强
与其他模式的关系
- 与适配器模式:适配器改变接口,装饰器增强功能
- 与代理模式:代理控制访问,装饰器添加功能
- 与组合模式:装饰器可视为只有一个组件的组合
- 与策略模式:策略改变行为核心,装饰器添加外围功能
JDK 中的装饰器模式
- Java I/O 流体系(
FilterInputStream
/FilterOutputStream
) - Java 集合框架的装饰方法(
Collections.unmodifiableCollection()
) - Servlet API 中的
HttpServletRequestWrapper
- JavaBeans 的
PropertyChangeSupport
注意事项
- 保持组件接口简洁(避免装饰器实现不必要的方法)
- 控制装饰层数(避免过度复杂)
- 考虑装饰器顺序(功能叠加可能有顺序依赖)
- 注意性能影响(多层包装增加调用开销)
- 提供适当的工厂方法简化装饰过程