装饰器模式(Decorator Pattern)

定义

装饰器模式是一种​​结构型设计模式​​,允许​​动态地为对象添加新功能​​,而无需修改其原始类。它通过将对象包装在装饰器类中,以​​组合代替继承​​,实现功能的灵活扩展(如 Java I/O 流、GUI 组件样式增强)。


UML 类图​

设计模式之结构型:装饰器模式_装饰器模式

核心角色

  • Component:核心对象接口(如咖啡、文本处理器),定义基础功能。
  • ConcreteComponent:具体的基础对象实现(如黑咖啡、文件读取器)。
  • Decorator:装饰器抽象类,持有 Component 的引用并实现其接口(核心设计)。
  • ConcreteDecorator:具体的装饰器类,添加额外功能(如加糖、加密、压缩)。

优点​

  • 动态扩展功能​​:无需修改原有类,通过装饰器链式叠加功能(如 new CompressionDecorator(new EncryptionDecorator(fileReader)))。
  • ​​避免继承爆炸​​:替代多层继承(如 Coffee → MilkCoffee → SugarMilkCoffee…),减少子类数量。
  • ​​开闭原则​​:新增功能时只需添加装饰器类,无需修改已有代码。
  • ​​灵活组合​​:装饰器可以任意顺序叠加(如先压缩再加密,或先加密再压缩)。

缺点​​

  • 复杂度提升​​:装饰器层级过多时,代码可读性和调试难度增加(如嵌套 5 层装饰器)。
  • ​​初始化冗余​​:创建装饰器对象链可能涉及多个对象的实例化,增加资源消耗。
  • ​​接口一致性风险​​:装饰器必须与原始对象接口完全一致,否则会导致调用失败。

​​代码示例(Java)​​

咖啡与调料装饰器​​

// 核心组件接口:咖啡
interface Coffee {
    double getCost();
    String getDescription();
}

// 具体组件:黑咖啡
class BlackCoffee implements Coffee {
    @Override
    public double getCost() {
        return 2.0;
    }

    @Override
    public String getDescription() {
        return "黑咖啡";
    }
}

// 抽象装饰器
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    @Override
    public double getCost() {
        return decoratedCoffee.getCost();
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}

// 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.5;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + " + 糖";
    }
}

// 具体装饰器:加牛奶
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 1.0;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + " + 牛奶";
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Coffee coffee = new MilkDecorator(new SugarDecorator(new BlackCoffee()));
        System.out.println(coffee.getDescription());  // 输出:黑咖啡 + 糖 + 牛奶
        System.out.println("价格:" + coffee.getCost()); // 输出:3.5
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.

​总结​​:装饰器模式通过​​组合和委托​​实现功能的动态扩展,特别适合需要​​灵活叠加功能​​且​​避免继承副作用​​的场景。其核心是​​装饰器与原始对象实现相同接口​​,并通过链式调用实现功能增强。