Introducción: Capas que suman valor
Decorator permite añadir comportamiento a objetos sin modificar su clase original. Es ideal cuando no quieres crear una explosión de subclases por cada combinación de funcionalidades.
Prompt: Layered translucent materials stacked, soft light, abstract minimal design.
1. Naturaleza: Capas protectoras
Las cebollas tienen capas. Cada capa añade protección sin cambiar la esencia de la cebolla. Eso es Decorator: añadir responsabilidad sin alterar el núcleo.
Prompt: Onion cross-section showing layers, macro photography, high detail.
2. Mundo Real: Cafés con extras
Un café puede ser base, pero puedes añadir leche, canela o caramelo. Cada extra es un decorator que suma costo y descripción.
Prompt: Latte with cinnamon and caramel drizzle, cozy cafe lighting, shallow depth of field.
3. Implementación en C#: Código Paso a Paso
3.1 Componente base
public interface ICafe
{
string ObtenerDescripcion();
decimal ObtenerCosto();
}
3.2 Componente concreto
public class CafeSimple : ICafe
{
public string ObtenerDescripcion() => "Café simple";
public decimal ObtenerCosto() => 1.50m;
}
3.3 Decorator base
public abstract class CafeDecorator : ICafe
{
protected ICafe _cafe;
protected CafeDecorator(ICafe cafe) { _cafe = cafe; }
public virtual string ObtenerDescripcion() => _cafe.ObtenerDescripcion();
public virtual decimal ObtenerCosto() => _cafe.ObtenerCosto();
}
3.4 Decorators concretos
public class ConLeche : CafeDecorator
{
public ConLeche(ICafe cafe) : base(cafe) { }
public override string ObtenerDescripcion() => base.ObtenerDescripcion() + ", con leche";
public override decimal ObtenerCosto() => base.ObtenerCosto() + 0.50m;
}
public class ConCanela : CafeDecorator
{
public ConCanela(ICafe cafe) : base(cafe) { }
public override string ObtenerDescripcion() => base.ObtenerDescripcion() + ", con canela";
public override decimal ObtenerCosto() => base.ObtenerCosto() + 0.30m;
}
3.5 Uso
ICafe miCafe = new CafeSimple();
miCafe = new ConLeche(miCafe);
miCafe = new ConCanela(miCafe);
Console.WriteLine(miCafe.ObtenerDescripcion());
Console.WriteLine($"Costo: {miCafe.ObtenerCosto()} €");
4. Decorator vs Composite
Composite compone estructuras jerárquicas. Decorator añade funcionalidades de forma dinámica. Ambos usan composición, pero con intenciones distintas.
5. Diagrama UML
Prompt: UML diagram of Decorator pattern, clean vector, labels in Spanish.
Prompt: Stack of layered object icons showing decoration, modern infographic style.
⚠️ Cuándo NO Usar Decorator
- Si las combinaciones posibles son muy pocas, una clase simple puede ser suficiente.
- Si necesitas modificar el comportamiento interno de forma profunda.
💪 Ejercicio
Crea un sistema de notificaciones donde puedas añadir decoradores: ConEmail, ConSMS, ConSlack.
Conclusión
Decorator es la forma elegante de sumar funcionalidades sin herencia explosiva. Piensa en capas.