Los decoradores son un patrón de diseño estructural que se utiliza para agregar funcionalidad adicional a objetos existentes sin modificar su estructura. Este patrón es especialmente útil cuando se desea extender las capacidades de un objeto de manera dinámica y flexible. En C#, los decoradores se implementan a menudo utilizando interfaces y herencia.
A continuación, se presentan los conceptos clave relacionados con los decoradores en C#:
- Componente Base (Component): Es la interfaz común que define las operaciones básicas que los objetos concretos y los decoradores deben implementar. Representa la estructura base de los objetos.
- Componente Concreto (Concrete Component): Es la clase que implementa la interfaz del componente base. Representa el objeto original al que se le agregarán funcionalidades adicionales mediante decoradores.
- Decorador (Decorator): Es una clase abstracta que también implementa la interfaz del componente base. Contiene una referencia a un objeto del componente base y actúa como una envoltura alrededor de ese objeto. El decorador agrega funcionalidad adicional antes o después de llamar a las operaciones del componente base.
- Decorador Concreto (Concrete Decorator): Son las clases concretas que extienden la funcionalidad de los decoradores abstractos. Cada decorador concreto implementa su propia lógica de decoración y llama a las operaciones del componente base, además de agregar su propia funcionalidad.
- Uso de Decoradores: Los objetos decoradores se pueden apilar en capas, lo que permite una composición flexible de funcionalidades. Puedes agregar uno o más decoradores a un objeto concreto para extender su funcionalidad.
- Beneficios de los Decoradores: Los decoradores permiten extender objetos sin cambiar su código existente. Esto promueve el principio de apertura/cierre (OCP) del diseño orientado a objetos, que establece que las clases deben estar abiertas para la extensión pero cerradas para la modificación.
Ejemplo de Decoradores en C#:
// Componente Base (Interfaz)
public interface ICar
{
string GetDescription();
double GetCost();
}
// Componente Concreto
public class BasicCar : ICar
{
public string GetDescription()
{
return "Basic Car";
}
public double GetCost()
{
return 20000;
}
}
// Decorador Abstracto
public abstract class CarDecorator : ICar
{
protected ICar _car;
public CarDecorator(ICar car)
{
_car = car;
}
public virtual string GetDescription()
{
return _car.GetDescription();
}
public virtual double GetCost()
{
return _car.GetCost();
}
}
// Decorador Concreto
public class SportsCar : CarDecorator
{
public SportsCar(ICar car) : base(car)
{
}
public override string GetDescription()
{
return base.GetDescription() + ", Sports Package";
}
public override double GetCost()
{
return base.GetCost() + 5000;
}
}
En este ejemplo, tenemos un componente base (ICar
) y un componente concreto (BasicCar
). Luego, creamos un decorador abstracto (CarDecorator
) y un decorador concreto (SportsCar
) que agrega una funcionalidad de paquete deportivo a un automóvil básico.
Los decoradores permiten extender las capacidades del objeto ICar
original de manera flexible y sin modificar su código. Esto facilita la creación de objetos con funcionalidades personalizadas según las necesidades de la aplicación.