第3章:装饰者模式(Decorator Pattern)
一、导读
1.1 本章学习目标
第3章讲解装饰者模式——一种动态地给对象添加额外职责的设计模式。相比继承,装饰者提供了更灵活的功能扩展方式。
1.2 为什么第三章如此重要
装饰者模式体现了"开放-关闭原则"——对扩展开放,对修改关闭。它是替代继承的有力工具,在 Java I/O、GUI 组件等场景中广泛应用。
1.3 核心问题引导
装饰者模式如何替代继承来扩展功能?
装饰者和被装饰对象有什么关系?
如何避免装饰者层次过深?
装饰者模式在 Java I/O 中如何应用?
二、核心概念详解
2.1 装饰者模式的结构
┌────────────────┐
│ <<interface>> │
│ Component │
│────────────────│
│ + operation() │
└────────────────┘
▲
│
┌─────┴──────┐ ┌────────────────┐
│ Concrete │ │ <<abstract>> │
│ Component │ │ Decorator │
│─────────────│ │────────────────│
│+ operation()│ │ - component │
└─────────────┘ │────────────────│
│ + operation() │
└────────────────┘
▲
┌─────┴──────┐
│ Concrete │
│ Decorator │
│─────────────│
│+ operation()│
│ + addedBehavior()│
└─────────────┘2.2 实现
java
// 组件接口
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() { return description; }
public abstract double cost();
}
// 装饰者基类
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
// 具体组件
public class Espresso extends Beverage {
public Espresso() { description = "Espresso"; }
public double cost() { return 1.99; }
}
public class HouseBlend extends Beverage {
public HouseBlend() { description = "House Blend Coffee"; }
public double cost() { return 0.89; }
}
// 具体装饰者
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) { this.beverage = beverage; }
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() { return 0.20 + beverage.cost(); }
}
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) { this.beverage = beverage; }
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() { return 0.10 + beverage.cost(); }
}
// 使用
Beverage beverage = new Espresso();
beverage = new Mocha(beverage);
beverage = new Whip(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());
// Espresso, Mocha, Whip $2.292.3 开放-关闭原则
装饰者模式完美体现了开放-关闭原则:
- 对扩展开放:可以添加新的装饰者来增加新功能。
- 对修改关闭:不需要修改现有代码。
三、实战案例
3.1 Java I/O 中的装饰者
java
// Java I/O 大量使用装饰者模式
InputStream in = new FileInputStream("file.txt"); // 基础组件
in = new BufferedInputStream(in); // 装饰者:缓冲
in = new DataInputStream(in); // 装饰者:数据读取
// 可以动态组合不同的装饰者
InputStream in2 = new FileInputStream("file.txt");
in2 = new GZIPInputStream(in2); // 装饰者:解压缩
in2 = new BufferedInputStream(in2); // 装饰者:缓冲四、本章小结
装饰者模式通过组合而非继承来扩展功能,体现了开放-关闭原则。Java I/O 是装饰者模式的经典应用。
五、思考与练习
装饰者模式和适配器模式有什么区别?
装饰者层次过深会有什么问题?
如何用装饰者模式实现日志功能?
Java I/O 中还有哪些装饰者的例子?
装饰者模式对性能有什么影响?