terminal

codeando_simple

terminal

menu

terminal

search_module

guest@codeandosimple: ~/system/search $ grep -r "" .

Press [ENTER] to execute search

Status

Engine: Ready

Database: Online

Index: V2.1.0_LATEST

bash — cat decorator.md
guest@codeandosimple: ~/blog/design-patterns $ cat decorator.md

Patrón Decorator_

// "Lo único imposible es aquello que no intentas" - Jean-Paul Sartre

# Propósito

El patrón Decorator permite agregar responsabilidades adicionales a un objeto de manera dinámica, en tiempo de ejecución, sin alterar la estructura de clases existentes.

Es especialmente útil para extender funcionalidades de manera flexible y reutilizable.

# Problema

La necesidad de extender la funcionalidad de una clase de manera dinámica, sin recurrir a la herencia, que genera una jerarquía rígida y menos flexible.

# Solución

La solución que propone el Decorator es envolver el objeto original en un objeto “decoradorâ€, que agregue la funcionalidad deseada.

  • Decoración de Objetos: Extiende la funcionalidad envolviéndolos con clases decoradoras.

  • Combinación Flexible: Permite combinar funcionalidades adicionales de forma flexible al usar múltiples decoradores.

# Estructura

Estructura UML Decorator

# Participantes

  • Component: Interfaz para objetos a los que se les quiere agregar responsabilidades.
  • ConcreteComponent: Objeto que se va a decorar.
  • Decorator: Clase abstracta que envuelve un objeto Component.
  • ConcreteDecorator: Añade funcionalidades al Component.

# Cuándo Usarlo

  • Agregar responsabilidades dinámicamente y de manera transparente.

  • Cuando la extensión mediante herencia no es viable o práctica.

# Ventajas

  • verified

    Mayor Flexibilidad: Responsabilidades dinámicas.

  • verified

    Evita clases sobrecargadas: Separa funcionalidades opcionales.

  • verified

    Combinación y Reutilización: Fácil mezcla de comportamientos.

# Desventajas

  • warning

    Complejidad: Múltiples capas pequeñas.

  • warning

    Configuración: Difícil de configurar con muchas capas.

  • warning

    Identificación: Difícil ver el objeto base.

# Ejemplo: Cafetería personalizable

Estamos desarrollando un sistema que necesita ofrecer gran variedad de cafés personalizables (leche, azúcar, crema, etc.).

Problema

Crear una clase para cada combinación generaría explosión de clases difícil de mantener.

Solución planteada

Usamos Decorator para agregar dinámicamente ingredientes al café base. Cada decorador añade su propio costo y descripción.

Ejemplo Decorator Café

# Código Java

interface Coffee {
    double getCost();
    String getDescription();
}

class SimpleCoffee implements Coffee {
    public double getCost() { return 2.0; }
    public String getDescription() { return "Café simple"; }
}

abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;
    public CoffeeDecorator(Coffee coffee) { this.decoratedCoffee = coffee; }
    public double getCost() { return decoratedCoffee.getCost(); }
    public String getDescription() { return decoratedCoffee.getDescription(); }
}

class WithMilk extends CoffeeDecorator {
    public WithMilk(Coffee coffee) { super(coffee); }
    public double getCost() { return super.getCost() + 0.5; }
    public String getDescription() { return super.getDescription() + ", con leche"; }
}

public class Client {
    public static void main(String[] args) {
        Coffee myCoffee = new SimpleCoffee();
        myCoffee = new WithMilk(myCoffee);
        myCoffee = new WithSugar(myCoffee);
        System.out.println("Costo: " + myCoffee.getCost());
    }
}

# Mapeo Participantes

  • Coffee (Component): Interfaz común.
  • SimpleCoffee (ConcreteComponent): Componente base.
  • CoffeeDecorator (Decorator): Clase base para decoradores.
  • WithMilk, WithSugar (ConcreteDecorators): Agregadores de funcionalidad.
  • Client: Ensambla cafés con ingredientes.

# Conclusiones

El patrón Decorator da una solución flexible y escalable, facilitando la adición de nuevos ingredientes en el futuro sin modificar el código existente.

# Patrones relacionados

Strategy

Decorator cambia el exterior; Strategy el interior de un objeto.

Composite

Decorator puede verse como un composite con un solo componente.

Adapter

Decorator cambia responsabilidades; Adapter cambia la interfaz.