PATRONES 101 - DECORATOR

La necesidad de investigar sobre este patrón se presenta cuando necesitas agregar funcionalidades adicionales u otras características a la clase sin complicar el código o la lógica en sí, la mejor manera de explicarlo es con un ejemplo:

Imaginen una cafetería que posee varias bebidas, por cada bebida hay un precio específico y el cliente puede agregar complementos a la bebida que no son exclusivos de la misma y que por consiguiente agregan un monto adicional al precio final y una nueva descripción a la Bebida en cuestión, como:"Mocachino, Canela, Suspiro, Fresas, $45.00" por decir algo

Partiendo de esto tenemos las siguientes entidades y sus tipos:

Bebidas:
- Batida
- Expreso
- Descafeinado
- Mocachino
- Jugo Natural

Complementos:
- Cada servicio puede contener: Leche de Soja, Soja, Crema, Frutas y mas...

Veamos el código en Java:

// Clase Abstracta que define la estructura base de la Bebida
public abstract class Bebida {
  String descripcion = "Bebida sin definir";
  public String getDescripcion() {
    return descripcion;  
  }

  public abstract double precio();
}

// Ahora la clase que representa una Bebida en concreto
public class Batida extends Bebida {
  public Batida() {
    descripcion = "Batida";
  } 

  public double precio() {
    return 45;
  }
}

// Veamos otra Bebida
public class Mocachino extends Bebida {
  public Mocachino() {
    descripcion = "Mocachino";
  }

  public double precio() {
    return 35;
}

// Antes de crear los complementos de las Bebidas debemos
// crear la clase que DECORA a los objetos Bebida con los
// complementos que luego seran agregados
public abstract class DecoradorComplementos extends Bebida {
  public abstract String getDescripcion();
}

// Como ya tenemos la clase que DECORA a los objetos procedemos
// a crear los complementos
public class Leche extends DecoradorComplementos {
  Bebida bebida; 

  // Se necesita una instancia de la clase bebida para decorar
  public Leche(Bebida bebida) {
    this.bebida = bebida;
  }

  public String getDescripcion() {
    return bebida.getDescripcion() + ", Leche";
  }

  public double precio() {
    return 10 + bebida.precio();
  }
}

// Finalmente la implementacion (Uso) de estas clases seria
public class Cafeteria {
  public static void main(String[] args) {
    Bebida cafeMocachino = new Mocachino();
    Bebida batidaEspecial = new Batida();

    // Despachemos el Cafe Mocachino sin complemento
    System.out.println(cafeMocachino.getDescripcion() + "  " + cafeMocachino.precio());

    // Ahora la batida con un complemento
    // Le pasamos la instancia de la bebida al complemento
    batidaEspecial = new Leche(batidaEspecial); 
    System.out.println(batidaEspecial.getDescripcion() + " " + batidaEspecial.precio());
  }
}
// El resultado de esta ejecucion seria:
Mocachino $35
Batida, Leche $55

En lo adelante para Nuevas Bebidas y Complementos la implementacion mas sencilla y rapida debido a esta forma de distribuir las responsabilidades.

Hasta la próxima...

Comentarios

Entradas populares