DEV Community

Higor Diego
Higor Diego

Posted on

Pattern - Decorator

Pattern decorator

The Decorator design pattern has its roots in object-oriented programming and was formally described by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides in the book "Design Patterns: Elements of Reusable Object-Oriented Software". Reusable Object Oriented Software).

The Decorator pattern is a software design pattern that allows you to dynamically add additional responsibilities to an individual object without affecting the behavior of other objects of the same type. This is accomplished by creating decorator objects that wrap around the original object and provide additional functionality. The Decorator pattern is used to add behaviors or attributes to an object without having to modify its class or create subclasses.

The Decorator pattern can be used in many cases, including:

  • Add responsibilities dynamically to an individual object, without affecting other objects of the same type.
  • Allow responsibilities to be added and removed independently of each other.
  • Apply optional responsibilities to objects without having to modify their class or create subclasses.
  • Provide an alternative to using multiple inheritance to extend the functionality of an object.

Common usage examples include adding additional functionality to objects such as forms, GUI components, file objects, etc.


class BaseComponent {
   operation() {
     return "base component";
   }
}


class Decorator {
   constructor(component) {
     this.component = component;
   }

   operation() {
     return this.component.operation();
   }
}

// Concrete decorators
class DecoratorExampleA extends Decorator {
   operation() {
     return `DecoratorExampleA(${this.component.operation()})`;
   }
}

class DecoratorExampleB extends Decorator {
   operation() {
     return `DecoratorExampleB(${this.component.operation()})`;
   }
}

// Using the decorator
const component = new BaseComponent();
console.log(component.operation()); // "base component"

const decoratorA = new DecoratorExampleA(component);
const decoratorB = new DecoratorExampleB(decoratorA);
console.log(decoratorB.operation()); // "ConcreteDecoratorB(ConcreteDecoratorA(Component))"
Enter fullscreen mode Exit fullscreen mode

The BaseComponent class is the base component that defines the basic operation. The Decorator class is the base class for all decorators which is responsible for wrapping the base component and providing its operation.

The DecoratorExampleA and DecoratorExampleB classes are the decorator classes that extend the Decorator class and provide additional functionality to the base component. They override the operation and add their own functionality to the base operation.

The code defines an instance of the base component BaseComponent and then creates two decorator instances DecoratorExampleA and DecoratorExampleB, which wrap around the base component and add their own functionality to the base operation.

When printing the result of the B decorator operation, we see that the additional functionality of the A and B decorators is applied to the base component's base operation.

Simple, right?

The Decorator pattern can be useful in many situations where you need to dynamically add additional responsibilities to objects. Some common situations where the Decorator pattern is used include:

  • Add additional functionality to objects without changing their basic structure.
  • Dynamically add additional responsibilities to objects without changing their class.
  • Apply different behaviors to objects without using inheritance.
  • Control the composition of objects to apply additional behaviors to them.
  • Implement optional functionality in objects, without having to change their original source code.

The Decorator pattern is widely used in libraries and frameworks such as Angular, React, etc. It's a powerful approach to dynamically adding responsibilities to objects, preserving the basic structure of objects and allowing greater flexibility in their behavior.

Conclusion

In summary, the Decorator pattern provides a flexible way to add behaviors to objects without affecting their underlying structure. It is a viable alternative to inheritance for extending the functionality of objects at runtime.

Hope this helps, until next time.

Top comments (0)