一、模式定义
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
二、核心角色
-
Component(组件接口)
- 定义被装饰对象的公共接口
-
ConcreteComponent(具体组件)
- 实现基础功能的具体类
-
Decorator(装饰者基类)
- 持有Component引用,实现Component接口
-
ConcreteDecorator(具体装饰者)
- 添加具体装饰功能的实现类
三、经典实现(咖啡店订单系统)
// 1. 组件接口
public interface Coffee {
String getDescription();
double cost();
}
// 2. 具体组件
public class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "Simple Coffee";
}
@Override
public double cost() {
return 1.0;
}
}
// 3. 装饰者基类
public abstract class CoffeeDecorator implements Coffee {
protected final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
@Override
public double cost() {
return decoratedCoffee.cost();
}
}
// 4. 具体装饰者
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", Milk";
}
@Override
public double cost() {
return super.cost() + 0.5;
}
}
public class MochaDecorator extends CoffeeDecorator {
public MochaDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", Mocha";
}
@Override
public double cost() {
return super.cost() + 0.7;
}
}
// 5. 客户端使用
public class CoffeeShop {
public static void main(String[] args) {
Coffee order = new SimpleCoffee();
System.out.println(order.getDescription() + " $" + order.cost());
order = new MilkDecorator(order);
System.out.println(order.getDescription() + " $" + order.cost());
order = new MochaDecorator(order);
System.out.println(order.getDescription() + " $" + order.cost());
}
}
四、模式结构UML
_________________________
| Component |
|-------------------------|
| + getDescription() |
| + cost() |
|_________________________|
▲
___________|___________
| |
_________▼_________ ______▼_______
| ConcreteComponent | | Decorator |
|-------------------| |--------------|
| + getDescription()| | - component |
| + cost() | |______________|
|___________________| ▲
_________|_________
| |
_______▼_______ _______▼_______
| ConcreteDecoratorA | | ConcreteDecoratorB |
|--------------------| |--------------------|
| + addedBehavior() | | + addedBehavior() |
|____________________| |____________________|
五、模式优劣分析
优势:
- 动态扩展功能,比继承更灵活
- 符合开闭原则,无需修改现有代码
- 支持多层嵌套装饰
- 不同装饰类可*组合
劣势:
- 多层装饰增加代码复杂度
- 装饰顺序影响最终结果
- 可能产生大量小类
- 调试困难(需逐层检查装饰)
六、应用场景
-
动态扩展对象功能
(如为图形界面组件添加边框、滚动条) -
撤销功能实现
(通过装饰记录操作历史) -
数据流处理
(Java I/O中的缓冲、加密处理) -
权限控制
(通过装饰添加权限校验层) -
日志记录
(为业务逻辑添加日志装饰)
七、Java标准库应用
Java I/O流典型实现:
// 多层装饰示例
InputStream in = new FileInputStream("data.txt");
in = new BufferedInputStream(in); // 添加缓冲功能
in = new GZIPInputStream(in); // 添加解压缩功能
in = new Base64InputStream(in); // 添加Base64解码
// 自定义装饰者示例
class UppercaseInputStream extends FilterInputStream {
public UppercaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1) ? c : Character.toUpperCase(c);
}
}
八、高级应用技巧
透明性控制
通过接口继承保持装饰透明性:
interface Window {
void draw();
}
class BasicWindow implements Window { /*...*/ }
abstract class WindowDecorator implements Window {
protected Window window;
// 不暴露额外方法
}
装饰顺序控制
使用建造者模式管理装饰顺序:
public class CoffeeBuilder {
private Coffee coffee = new SimpleCoffee();
public CoffeeBuilder addMilk() {
coffee = new MilkDecorator(coffee);
return this;
}
public Coffee build() {
return coffee;
}
}
动态移除装饰
实现装饰栈管理:
public class UndoableCoffee implements Coffee {
private Deque<Coffee> stack = new ArrayDeque<>();
public UndoableCoffee(Coffee coffee) {
stack.push(coffee);
}
public void addDecorator(CoffeeDecorator decorator) {
stack.push(decorator);
}
public void undo() {
if (stack.size() > 1) {
stack.pop();
}
}
// 实现Coffee接口方法...
}
九、最佳实践建议
-
保持组件接口简洁
避免装饰者需要实现过多无关方法 -
控制装饰层次深度
建议不超过4层装饰 -
优先使用透明装饰
保持装饰前后接口一致 -
注意线程安全问题
对于可变状态装饰器,使用同步控制 -
性能敏感场景慎用
多层装饰可能影响性能(建议结合对象池)