Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Sure! The Decorator Pattern is a design pattern that allows us to add additional behavior or functionality to an object dynamically at runtime. Let me explain the pattern using the practical illustration of a coffee shop.

Imagine you own a coffee shop and want to provide your customers with different options to customize their coffee. One way to achieve this is by using the Decorator Pattern.

First, you need to define your base coffee class which will have the basic properties of any coffee, such as the type of coffee and its price. Here's an example:

class Coffee {
  constructor(type, price) {
    this.type = type;
    this.price = price;
  }

  getDescription() {
    return `${this.type} coffee (${this.price})`;
  }
}

Next, you can create decorators that modify the coffee by adding additional features. For example, let's say you want to offer your customers the option to add milk or sugar to their coffee.

class MilkDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  getDescription() {
    return `${this.coffee.getDescription()} + milk`;
  }

  getPrice() {
    return this.coffee.price + 1.5;
  }
}

class SugarDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  getDescription() {
    return `${this.coffee.getDescription()} + sugar`;
  }

  getPrice() {
    return this.coffee.price + 1;
  }
}

In the above code, we created two decorators, MilkDecorator and SugarDecorator which add additional behavior to the coffee by modifying the getDescription() and getPrice() methods accordingly.

Finally, when a customer orders a customized coffee, you can dynamically add decorators to the coffee object. For example, if a customer orders a coffee with milk and sugar, you can do the following:

let myCoffee = new Coffee("Espresso", 2.5);
myCoffee = new MilkDecorator(myCoffee);
myCoffee = new SugarDecorator(myCoffee);

console.log(myCoffee.getDescription()); // Output: Espresso coffee (2.5) + milk + sugar
console.log(myCoffee.getPrice()); // Output: 5

In the above code, we first created a coffee object of the base class (Espresso coffee priced at 2.5). We then added a MilkDecorator and a SugarDecorator to the coffee object using the decorators. The getDescription() method of the coffee object now returns "Espresso coffee (2.5) + milk + sugar". Similarly, the getPrice() method returns the total price of the coffee (2.5 + 1.5 + 1 = 5).

This is a practical example of how the Decorator Pattern can be used to add additional behavior or functionality to an object dynamically at runtime.