Skip to content

Latest commit

 

History

History
88 lines (63 loc) · 3.45 KB

DecoratorPattern.md

File metadata and controls

88 lines (63 loc) · 3.45 KB

Decorator Pattern

The Decorator Pattern is a structural design pattern that allows behavior to be added to individual objects dynamically, without affecting the behavior of other objects from the same class. It's particularly useful when you need to add functionality to objects in a flexible and reusable way.

Example in Node.js:

In this example, the Coffee class represents the base component. CoffeeDecorator is the abstract decorator class, and Milk and Sugar are concrete decorators that add milk and sugar to the coffee, respectively. Clients can create various combinations of decorated coffees by stacking decorators on top of each other.

// Component interface
class Coffee {
  cost() {
    return 5;
  }

  description() {
    return 'Coffee';
  }
}

// Decorator
class CoffeeDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  cost() {}

  description() {}
}

// Concrete Decorator
class Milk extends CoffeeDecorator {
  cost() {
    return this.coffee.cost() + 2;
  }

  description() {
    return this.coffee.description() + ', Milk';
  }
}

// Concrete Decorator
class Sugar extends CoffeeDecorator {
  cost() {
    return this.coffee.cost() + 1;
  }

  description() {
    return this.coffee.description() + ', Sugar';
  }
}

// Usage
let coffee = new Coffee();
console.log(coffee.description()); // Output: Coffee
console.log(coffee.cost()); // Output: 5

coffee = new Milk(coffee);
console.log(coffee.description()); // Output: Coffee, Milk
console.log(coffee.cost()); // Output: 7

coffee = new Sugar(coffee);
console.log(coffee.description()); // Output: Coffee, Milk, Sugar
console.log(coffee.cost()); // Output: 8
Pros:
  1. Flexibility: Decorators allow you to add or remove responsibilities from objects at runtime, providing a flexible alternative to subclassing for extending functionality.

  2. Open/Closed Principle: The Decorator Pattern promotes the Open/Closed Principle by allowing the addition of new functionality without modifying existing code.

  3. Single Responsibility Principle: It helps in adhering to the Single Responsibility Principle by keeping each decorator focused on a single aspect of functionality.

  4. Composition over Inheritance: Instead of relying on inheritance to extend behavior, the Decorator Pattern uses composition, which is often considered a more flexible and preferable approach.

  5. Reusable Decorators: Decorators can be easily reused across different objects and classes, promoting code reuse and maintainability.

Cons:
  1. Complexity: Introducing multiple layers of decorators may lead to increased complexity, especially when dealing with a large number of decorators and interactions between them.

  2. Ordering Dependencies: The order in which decorators are applied can affect the behavior of the object, which may introduce subtle bugs if not managed properly.

  3. Performance Overhead: While the Decorator Pattern provides flexibility, it may also introduce a slight performance overhead due to the additional layers of abstraction and indirection involved.

  4. Interface Bloat: If decorators are not carefully designed, they may lead to interface bloat, where the interfaces of decorated objects become overly complex or cluttered.

  5. Dynamic Changes: While decorators allow dynamic changes to an object's behavior, they may also make it more difficult to predict the behavior of an object at runtime, especially when multiple decorators are involved.