装饰器模式 (Decorator Pattern)
装饰器模式是一种 结构型设计模式,它允许动态地向对象添加新的功能,同时又不改变其结构。这种模式通过对象组合来实现,比通过继承扩展功能更加灵活。
原理
- 核心思想:通过将对象包装在一系列装饰器中,增强或修改对象的功能,而无需更改对象本身的代码。
 - 适用场景: 
  
- 希望动态地扩展一个类的功能,而不使用继承。
 - 需要为一个对象提供多种行为组合,且行为的数量动态变化。
 
 - 参与角色: 
  
- Component(抽象组件):定义一个对象接口,可以动态地为其添加职责。
 - ConcreteComponent(具体组件):实现抽象组件的类,是被装饰的对象。
 - Decorator(装饰器):实现抽象组件,并持有一个具体组件的引用。
 - ConcreteDecorator(具体装饰器):扩展装饰器,提供额外的功能。
 
 
优点
- 动态扩展功能:无需修改原始类和其他装饰器类即可扩展功能。
 - 遵循开闭原则:通过添加新装饰器类来实现功能扩展。
 - 灵活组合:装饰器可以任意组合使用。
 
缺点
- 复杂性增加:过多的装饰器可能导致系统变得复杂。
 - 调试困难:在装饰器链中定位问题可能较为困难。
 
示例代码
场景描述
假设有一个咖啡订单系统,不同的咖啡可以加不同的调料(如牛奶、糖)。咖啡本身和调料的价格需要动态组合计算,且系统应具备良好的扩展性。
1. 定义抽象组件
// 抽象组件
public interface Coffee {
    String getDescription(); // 获取描述
    double getCost();        // 获取价格
}
 
2. 创建具体组件
// 具体组件:基础咖啡
public class BasicCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "Basic Coffee";
    }
    @Override
    public double getCost() {
        return 5.0;
    }
}
 
3. 创建装饰器抽象类
// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee; // 持有组件的引用
    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
    @Override
    public String getDescription() {
        return coffee.getDescription();
    }
    @Override
    public double getCost() {
        return coffee.getCost();
    }
}
 
4. 创建具体装饰器
// 牛奶装饰器
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    @Override
    public String getDescription() {
        return coffee.getDescription() + ", Milk";
    }
    @Override
    public double getCost() {
        return coffee.getCost() + 1.5; // 牛奶价格
    }
}
// 糖装饰器
public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }
    @Override
    public String getDescription() {
        return coffee.getDescription() + ", Sugar";
    }
    @Override
    public double getCost() {
        return coffee.getCost() + 0.5; // 糖价格
    }
}
 
5. 客户端代码
public class DecoratorPatternExample {
    public static void main(String[] args) {
        // 基础咖啡
        Coffee coffee = new BasicCoffee();
        System.out.println(coffee.getDescription() + " -> $" + coffee.getCost());
        // 加牛奶的咖啡
        coffee = new MilkDecorator(coffee);
        System.out.println(coffee.getDescription() + " -> $" + coffee.getCost());
        // 加牛奶和糖的咖啡
        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.getDescription() + " -> $" + coffee.getCost());
    }
}
 
输出结果
Basic Coffee -> $5.0
Basic Coffee, Milk -> $6.5
Basic Coffee, Milk, Sugar -> $7.0
 
UML 类图
         +----------------+         +--------------------+
         |    Coffee      |<>------>|  CoffeeDecorator   |
         +----------------+         +--------------------+
         |+ getDescription()        |+ getDescription()  |
         |+ getCost()               |+ getCost()         |
         +----------------+         +--------------------+
                ^                           ^
                |                           |
   +--------------------+         +--------------------+
   |   BasicCoffee      |         | MilkDecorator      |
   +--------------------+         +--------------------+
   |+ getDescription()  |         |+ getDescription()  |
   |+ getCost()         |         |+ getCost()         |
   +--------------------+         +--------------------+
 
使用场景
- 需要动态地增加功能:如图形编辑器中为图形对象添加功能(边框、阴影)。
 - 功能组合的场景:如不同装饰效果的叠加。
 - 避免继承扩展:用装饰器动态扩展功能而不引入过多的子类。
 
总结
- 装饰器模式是一种灵活的设计模式,可以在运行时动态地为对象添加功能。
 - 它有效避免了类爆炸问题,特别适合需要灵活组合的场景。
 - 通过对象组合,装饰器模式实现了强大的扩展能力,符合 开闭原则。
 










