domingo, 1 de mayo de 2016

Patrones de Diseño de Comportamiento Parte 1


13. Chain of Responsibility: Permite establecer una cadena de objetos receptores a través de los cuales se pasa una petición formulada por un objeto emisor. La idea es que cualquiera de los receptores pueden responder a la petición en función de un criterio establecido. En cadena los objetos receptores y pasa la petición a través de la cadena hasta que es procesada por algún objeto.
Busca evitar un montón de if - else largos y complejos en nuestro código, pero sobre todas las cosas busca evitar que el cliente necesite conocer toda nuestra estructura jerárquica y que rol cumple cada integrante de nuestra estructura. En múltiples ocasiones, un cliente necesita que se realice una función, pero o no conoce al servidor concreto de esa función o es conveniente que no lo conozca para evitar un gran acoplamiento entre ambos. Se utiliza cuando las peticiones emitidas por un objeto deben ser atendidas por distintos objetos receptores, no se sabe a priori cual es el objeto que me puede resolver el problema, cuando un pedido debe ser manejado por varios objetos, el conjunto de objetos que pueden tratar una petición debería ser especificado dinámicamente. La motivación detrás de este patrón es crear un sistema que puede servir a diversas solicitudes de manera jerárquica. En otras palabras, si un objeto que parte de un sistema no sabe cómo responder a una solicitud, la pasa a lo largo del árbol de objetos. Como el nombre lo implica, cada objeto de dicho árbol puede tomar la responsabilidad y atender la solicitud.

Diagrama UML

Ejemplo

Primero necesitará  definir la clase "Mensaje", la cual obtendrá a quien está dirigida la orden y cuáles son las instrucciones a ejecutar.
package cadena.de.responsabilidad;

public class Mensaje {

    private String para;
    private String contenido;

    public Mensaje(String para, String contenido) {
        this.para = para;
        this.contenido = contenido;
    }

    public String getPara() {
        return para;
    }

    public void setPara(String para) {
        this.para = para;
    }

    public String getContenido() {
        return contenido;
    }

    public void setContenido(String contenido) {
        this.contenido = contenido;
    }
  
}

Luego deberá  definir la clase abstracta "EjecutarOrdenAltoMando", la cual deberán extender cada uno de los elementos de su ejercito.

package cadena.de.responsabilidad;

abstract class EjecutarOrdenAltoMando {

    protected EjecutarOrdenAltoMando subAlterno;


    public void setSubAlterno(EjecutarOrdenAltoMando subAlterno){
        this.subAlterno = subAlterno;
    }

    public abstract void ejecutarOrden(Mensaje mensaje);

}

Ahora, cada sub-alterno que extienda la clase abstracta, deberá definir un mecanismo que permita discriminar si la orden enviada la debe ejecutar el, o en caso en contrario, enviar la orden a su sub-alterno.

package cadena.de.responsabilidad;

class GeneralMazingerZ extends EjecutarOrdenAltoMando {

    public void ejecutarOrden(Mensaje mensaje){
        if (mensaje.getPara().equals("OrdenGeneral")){
            System.out.println(mensaje.getContenido());
        }
        else if (subAlterno != null){
            subAlterno.ejecutarOrden(mensaje);
        }
    }

}
package cadena.de.responsabilidad;

class CoronelElVengador extends EjecutarOrdenAltoMando {

   public void ejecutarOrden(Mensaje mensaje){
       if (mensaje.getPara().equals("OrdenCoronel")){
           System.out.println(mensaje.getContenido());
       }
       else if (subAlterno != null){
           subAlterno.ejecutarOrden(mensaje);
       }
   }

}
package cadena.de.responsabilidad;

class SoldadoElGalatico extends EjecutarOrdenAltoMando {

    public void ejecutarOrden(Mensaje mensaje){
        if (mensaje.getPara().equals("OrdenSoldado")){
            System.out.println(mensaje.getContenido());
        }
        else{
            System.out.println("EL TIPO DE ORDEN NO EXISTE");
        }
    }

}

Finalmente, será muy fácil para Cerebro enviar un mensaje a su ejército, el simplemente dará la orden a su  "General" y listo !!

package cadena.de.responsabilidad;

public class Cerebro {

 public static Mensaje[] generarMensajes(){
        Mensaje mensajes [] = {
             new Mensaje("OrdenGeneral", "Ejecutar Orden General Mazinger Z"),
             new Mensaje("OrdenCoronel", "Ejecutar Orden Coronel El Vengador"),
             new Mensaje("OrdenSoldado", "Ejecutar Orden Soldado El Galatico"),
             new Mensaje("OrdenCoronel", "Ejecutar Orden Coronel El Vengador"),
             new Mensaje("OrdenGeneral", "Ejecutar Orden General Mazinger Z"),
             new Mensaje("OrdenSoldado", "Ejecutar Orden Soldado El Galatico") 
        };
        return mensajes;
    }

    public static EjecutarOrdenAltoMando configurarCadena(){
        EjecutarOrdenAltoMando generalMazingerZ = new GeneralMazingerZ();
     EjecutarOrdenAltoMando coronelElVengador = new CoronelElVengador();
     EjecutarOrdenAltoMando soldadoElGalatico = new SoldadoElGalatico();
     generalMazingerZ.setSubAlterno(coronelElVengador);
     coronelElVengador.setSubAlterno(soldadoElGalatico);
        return generalMazingerZ;
    }

    public static void main(String[] args) {
     EjecutarOrdenAltoMando generalMazingerZ = configurarCadena();
     for(Mensaje mensaje : generarMensajes()){
         generalMazingerZ.ejecutarOrden(mensaje);
     }
 }

}

14. Command: El patrón de comportamiento Command encapsula una petición dentro de un objeto, permitiendo parametrizar a los clientes con distintas peticiones, encolarlas, guardalas en un registro de sucesos o implementar un mecanismo de deshacer/repetir. En el contexto de programación actual un simple programa puede ejecutar decenas, o incluso centenares, de invocaciones a subprocesos o subprogramas. El patrón Command permite a los objetos de la interfaz hacer solicitudes de objetos de una aplicación no especificada convirtiendo la solicitud en un objeto. Este objeto pueder ser almacenado y movido como otros objetos. La clave de este patrón  es la clase abstracta command que declara una interfaz para ejecutar operaciones.

Diagrama UML.



 Ejemplo

 Crear una interface command.

public interface Order {
   void execute();
}
 Crear una clase petición.

public class Stock {
  
   private String name = "ABC";
   private int quantity = 10;

   public void buy(){
      System.out.println("Stock [ Name: "+name+",
         Quantity: " + quantity +" ] bought");
   }
   public void sell(){
      System.out.println("Stock [ Name: "+name+",
         Quantity: " + quantity +" ] sold");
   }
}

 Crear clases concreta implementando la interface Order.

public class BuyStock implements Order {
   private Stock abcStock;

   public BuyStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.buy();
   }
}
public class SellStock implements Order {
   private Stock abcStock;

   public SellStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.sell();
   }
}

Crear clases comando invoker.

import java.util.ArrayList;
import java.util.List;

   public class Broker {
   private List<Order> orderList = new ArrayList<Order>();

   public void takeOrder(Order order){
      orderList.add(order);      
   }

   public void placeOrders(){
 
      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}

Usa la clase Borker a tomar  y ejecutar comandos

public class CommandPatternDemo {
   public static void main(String[] args) {
      Stock abcStock = new Stock();

      BuyStock buyStockOrder = new BuyStock(abcStock);
      SellStock sellStockOrder = new SellStock(abcStock);

      Broker broker = new Broker();
      broker.takeOrder(buyStockOrder);
      broker.takeOrder(sellStockOrder);

      broker.placeOrders();
   }
}

15. Interpreter: Este patrón busca representar un lenguaje mediante reglas gramáticas. Para ello define estas reglas gramáticas y como interpretarlas. Utiliza una clase para representar una regla gramática. Si un tipo particular de problema se presenta frecuentamente, puede ser provechoso expresar los diferentes casos del problema como sentencias de un lenguaje simple. Difícilmente el desarrollador utilice este patrón en algún momento de su vida, lo que no quita que no sea patrón utilizado. La situación ideal que se debe considerar para aplicar este patrón es que exista un lenguaje sencillo que pueda interpretarse con palabras. Nuestro sistema tiene que ser capaz de reconocer sentencias de un lenguaje previamente conocido (mediante su gramática), poder evaluar expresiones del mismo y ser capaz de ejecutar las sentencias recibidas. Y se aplica cuando debemos trabajar  con sentencias de un lenguaje que nuestro lenguaje de programación no reconoce automáticamente. La gramática del lenguaje con el que debemos trabajares sencilla. Para gramáticas complejas se deben emplear técnicas concretas de la Teoríade Gramáticas Formales(scanners y parsers). No debe utilizarse si ya existe alguna clase nativa que intérprete este lenguaje.

Diagrama UML


 Ejemplo

Crear una interface Expresión.

public interface Order {
   void execute();
}

Crear una clase petición

public class Stock {
   
   private String name = "ABC";
   private int quantity = 10;

   public void buy(){
      System.out.println("Stock [ Name: "+name+",
         Quantity: " + quantity +" ] bought");
   }
   public void sell(){
      System.out.println("Stock [ Name: "+name+",
         Quantity: " + quantity +" ] sold");
   }
}

Crear clases concretas  implementando la interface Order.

public class BuyStock implements Order {
   private Stock abcStock;

   public BuyStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.buy();
   }
}


public class SellStock implements Order {
   private Stock abcStock;

   public SellStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.sell();
   }
}

Crear comando clase invoker.

import java.util.List;

   public class Broker {
   private List<Order> orderList = new ArrayList<Order>();

   public void takeOrder(Order order){
      orderList.add(order);      
   }

   public void placeOrders(){
 
      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}


Usa la clase Broker a tomar y ejecutar comandos

import java.util.ArrayList;
public class CommandPatternDemo {
   public static void main(String[] args) {
      Stock abcStock = new Stock();

      BuyStock buyStockOrder = new BuyStock(abcStock);
      SellStock sellStockOrder = new SellStock(abcStock);

      Broker broker = new Broker();
      broker.takeOrder(buyStockOrder);
      broker.takeOrder(sellStockOrder);

      broker.placeOrders();
   }
}
 

No hay comentarios:

Publicar un comentario