Skip to content

装饰模式

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许在不修改原始类的情况下动态地给对象添加功能。装饰模式通过创建一个包装对象(即装饰者),来包裹真实的对象,并在运行时动态地为这个对象添加新的行为或特性。

装饰模式的主要角色

  1. Component(组件接口):定义了被装饰的对象的接口,也可以是一个抽象类。
  2. ConcreteComponent(具体组件):实现了 Component 接口,是真正被装饰的对象。
  3. Decorator(装饰者):持有一个对 Component 对象的引用,并定义了一个与 Component 接口一致的接口。
  4. ConcreteDecorator(具体装饰者):扩展了 Component 的行为,通常会在操作前后执行一些额外的动作。

在 JavaScript 中的实现

下面是一个简单的例子来说明如何在 JavaScript 中使用装饰模式:

示例:咖啡店饮品定制系统

假设你正在开发一个咖啡店应用,客户可以定制自己的咖啡,比如添加牛奶、糖浆等。我们可以使用装饰模式来动态地增加这些选项。

javascript
// Component(组件接口)
class Beverage {
  constructor() {
    this.description = "Unknown Beverage";
  }

  getDescription() {
    return this.description;
  }

  cost() {
    throw new Error("This method should be overridden");
  }
}

// ConcreteComponent(具体组件)
class Espresso extends Beverage {
  constructor() {
    super();
    this.description = "Espresso";
  }

  cost() {
    return 1.99;
  }
}

// Decorator(装饰者)
class CondimentDecorator extends Beverage {
  beverage;

  constructor(beverage) {
    super();
    this.beverage = beverage;
  }

  getDescription() {
    return this.beverage.getDescription();
  }
}

// ConcreteDecorator(具体装饰者)
class Milk extends CondimentDecorator {
  constructor(beverage) {
    super(beverage);
  }

  getDescription() {
    return this.beverage.getDescription() + ", Milk";
  }

  cost() {
    return this.beverage.cost() + 0.1;
  }
}

class Mocha extends CondimentDecorator {
  constructor(beverage) {
    super(beverage);
  }

  getDescription() {
    return this.beverage.getDescription() + ", Mocha";
  }

  cost() {
    return this.beverage.cost() + 0.2;
  }
}

// 使用示例
let beverage = new Espresso();
console.log(`${beverage.getDescription()} $${beverage.cost().toFixed(2)}`); // 输出: Espresso $1.99

beverage = new Mocha(beverage);
console.log(`${beverage.getDescription()} $${beverage.cost().toFixed(2)}`); // 输出: Espresso, Mocha $2.19

beverage = new Milk(beverage);
console.log(`${beverage.getDescription()} $${beverage.cost().toFixed(2)}`); // 输出: Espresso, Mocha, Milk $2.29

代码解释

  • Beverage(组件接口):定义了饮料的基本属性和方法,包括获取描述和计算价格的方法。
  • Espresso(具体组件):实现了Beverage接口,表示具体的饮料类型——浓缩咖啡。
  • CondimentDecorator(装饰者):作为所有装饰者的基类,持有对Beverage对象的引用,并重写了getDescription方法。
  • Milk 和 Mocha(具体装饰者):继承自CondimentDecorator,分别代表向饮料中添加牛奶和摩卡的选项,并且各自增加了相应的费用。

应用场景

装饰模式适用于以下几种情况:

  • 当需要在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责时。
  • 当不能采用生成子类的方法进行扩充时,例如,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

通过使用装饰模式,可以在不改变现有对象的情况下,灵活地为其添加新功能,这对于需求经常变化的应用程序特别有用。此外,装饰模式还支持递归组合,允许你构建复杂的装饰链,从而实现更强大的功能扩展。

Released under the MIT License.