Decorador

El patr贸n Decorador (Decorator) es un patr贸n de dise帽o estructural que permite a帽adir din谩micamente funcionalidades a objetos en tiempo de ejecuci贸n sin alterar la estructura de las clases existentes. Se utiliza para extender las funcionalidades de los objetos de una manera flexible y reutilizable, implementando cada funcionalidad en clases decoradoras separadas.

Concepto del Patr贸n Decorador

Imagina que tienes una clase base, por ejemplo, una bebida, y quieres a帽adir opciones como leche, az煤car, chocolate, etc., sin modificar la clase base ni crear subclases para cada combinaci贸n posible. El patr贸n decorador permite esto a帽adiendo estas funcionalidades en tiempo de ejecuci贸n.

Ejemplo en TypeScript

Vamos a crear un ejemplo simple que demuestra c贸mo funciona el patr贸n decorador. En este ejemplo, consideraremos una aplicaci贸n que simula una cafeter铆a con diferentes tipos de caf茅 y opciones adicionales como leche y az煤car.

// Componente base
interface Coffee {
  getCost(): number;
  getDescription(): string;
}

// Clase concreta base
class SimpleCoffee implements Coffee {
  getCost(): number {
    return 10;
  }

  getDescription(): string {
    return "Simple coffee";
  }
}

// Decorador base
abstract class CoffeeDecorator implements Coffee {
  protected decoratedCoffee: Coffee;

  constructor(coffee: Coffee) {
    this.decoratedCoffee = coffee;
  }

  getCost(): number {
    return this.decoratedCoffee.getCost();
  }

  getDescription(): string {
    return this.decoratedCoffee.getDescription();
  }
}

// Decorador concreto: Milk
class WithMilk extends CoffeeDecorator {
  constructor(coffee: Coffee) {
    super(coffee);
  }

  getCost(): number {
    return this.decoratedCoffee.getCost() + 2;
  }

  getDescription(): string {
    return this.decoratedCoffee.getDescription() + ", with milk";
  }
}

// Decorador concreto: Sugar
class WithSugar extends CoffeeDecorator {
  constructor(coffee: Coffee) {
    super(coffee);
  }

  getCost(): number {
    return this.decoratedCoffee.getCost() + 1;
  }

  getDescription(): string {
    return this.decoratedCoffee.getDescription() + ", with sugar";
  }
}

// Uso del decorador
const simpleCoffee = new SimpleCoffee();
console.log(simpleCoffee.getDescription() + " costs $" + simpleCoffee.getCost());

const milkCoffee = new WithMilk(simpleCoffee);
console.log(milkCoffee.getDescription() + " costs $" + milkCoffee.getCost());

const sugarMilkCoffee = new WithSugar(milkCoffee);
console.log(sugarMilkCoffee.getDescription() + " costs $" + sugarMilkCoffee.getCost());

Explicaci贸n

  1. SimpleCoffee es la implementaci贸n b谩sica de la interfaz Coffee.

  2. CoffeeDecorator es una clase abstracta que implementa la interfaz Coffee y mantiene una referencia a un objeto Coffee. Todos los decoradores concretos extender谩n esta clase.

  3. WithMilk y WithSugar son decoradores concretos que a帽aden funcionalidades y costos adicionales al objeto Coffee.

  4. Al final, demostramos c贸mo se puede envolver un caf茅 simple con m煤ltiples decoradores para agregar leche y az煤car, mostrando c贸mo el patr贸n Decorador permite a帽adir din谩micamente funcionalidades.

Este patr贸n es muy 煤til para respetar el principio de responsabilidad 煤nica y el principio de abierto/cerrado, permitiendo que las clases est茅n abiertas para la extensi贸n pero cerradas para la modificaci贸n.

Last updated