lunes, 9 de mayo de 2016

Patrones de Diseño de Comportamiento Parte 4


22. Template Method: Es un patrón de diseño que define una estructura algorítmica en la súper clase, delegando la implementación a la subclases. Es decir, define una serie de pasos, en donde los pasos serán redefinidios en las subclases. Permite que las subclases redefinan ciertos pasos del algoritmo sin cambiar su estructura. Cuando se construyen jerarquías de clases complejas  para una aplicación, a menudo se duplican  distintas partes del código. Esa situación no es deseable, porque la intención es reutilizar todo el código que sea posible. La refactorización de código para que los métodos comunes estén en una superclase es un paso en la dirección correcta. El problema es que algunas veces una operación que ha sido refactorizada confía en la información específica que solamente está disponible en una subclase. Debido a esto, los desarrolladores a menudo deciden no refactorizar y aceptar la presencia de código duplicado en distintas clases.
Este patrón se vuelve de especial utilidad cuando es necesario realizar un algoritmo que sea común para muchas clases, pero con pequeñas variaciones entre una y otras. Para proporcionar un esqueleto para un método, permitiendo que las subclases redefinan partes específicas del método, para centralizar partes de un método que se definen en todos los subtipos de una clase, pero que siempre tiene una pequeña diferencia en cada subclase. Otro uso particular se da en la creación de sistemas de plugins. Por definición este patrón garantiza la existencia de distintos métodos en una clase que pueden ser sobrescritos por un descendiente.

Representación UML

Ejemplo

Cuando tienes a leer datos de los datos fuentes ejemplo CSV y base de datos entonces tu tiene a procesar que datos y generar  salida tal como archivos CSV. Con los tres pasos siguientes:

Leer datos de correspondiente fuentes de datos.
Datos de procesos.
Escribir salida a archivos CSV.


La clase perteneciente contiene template method llamado "parseDataAndGeneratedOutput" que consiste de pasos para leer datos, procesando datos y escrbiendo a archivo csv.
package org.arpit.javapostsforlearning; 
 
abstract public class DataParser { 
     
    //Template method 
    //This method defines a generic structure for parsing data 
    public void parseDataAndGenerateOutput() 
    { 
        readData(); 
        processData(); 
        writeData(); 
    } 
    //This methods will be implemented by its subclass 
    abstract void readData(); 
    abstract void processData(); 
     
    //We have to write output in a CSV file so this step will be same for all subclasses 
    public void writeData() 
    { 
        System.out.println("Output generated,writing to CSV"); 
    } 
}
 En clase perteneciente, CSV especifica pasos que son implementados en esta clase

package org.arpit.javapostsforlearning;
 
public class CSVDataParser extends DataParser {
 
    void readData() {
        System.out.println("Reading data from csv file");
    }
    void processData() {
        System.out.println("Looping through loaded csv file");    
    }
}

 En clase dadas, las base de datos específicas son implementadas en estas clases

package org.arpit.javapostsforlearning; 
 
public class DatabaseDataParser extends DataParser { 
 
    void readData() { 
        System.out.println("Reading data from database"); 
    } 
 
    void processData() { 
        System.out.println("Looping through datasets");         
    } 
}
 
 Y escribimos la clase Principal.

package org.arpit.javapostsforlearning;
 
public class TemplateMethodMain {
 
    /**
     * @author arpit mandliya
     */
    public static void main(String[] args) {
        
        CSVDataParser csvDataParser=new CSVDataParser();
        csvDataParser.parseDataAndGenerateOutput();
        System.out.println("**********************");
        DatabaseDataParser databaseDataParser=new DatabaseDataParser();
        databaseDataParser.parseDataAndGenerateOutput();
 
    }
 
}

23. Visitor: Busca separar un algoritmo de la estructura de un objeto. La operación se implementa de forma que no se modifique el código de las clases sobre las que opera. Si un objeto es el responsable de mantener un cierto tipo de información, entonces es lógico asignarle también la responsabilidad de realizar todas las operaciones necesarias sobre esa información. La operación se define en cada una de las clases que representa los posibles tipos sobre los que se aplica dicha operación, y por medio del polimorfismo y la vinculación dinámica se elige en tiempo de ejecución qué versión de la operación se debe ejecutar. De esta forma se evita un análisis de casos sobre el tipo  del parámetro. Este patrón se utiliza cuando una estructura de objetos contiene muchas clases de objetos con distintas interfaces  y se desea llevar a cabo operaciones sobre estos objetos que son distintas en cada clase concretas. Se quieren llevar a cabo muchas operaciones dispares sobre objetos de una estructura de objetos sin tener que incluir dichas operaciones en las clases. Las clases que definen la estructura de objetos no cambian, pero las operaciones que se llevan a cabo sobre ellas. Dado que este patrón separa un algoritmo de la estructura de un objeto, es ampliamente utilizado en intérpretes, compiladores y procesadores de lenguajes, en general. Se debe utilizar este patrón si se quiere realizar  un cierto número de operaciones, que no están  relacionadas entre sí, sobre instancias de un conjunto de clases, y no se quiere "contaminar" a dichas clases.

Representación UML


Ejemplo

Define una interface a representar un elemento.


public interface ComputerPart {
   public void accept(ComputerPartVisitor computerPartVisitor);
}

 Crear clases concretas extendiendo la clase anterior.

public class Keyboard implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

public class Monitor implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

public class Mouse implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

public class Computer implements ComputerPart {
  
   ComputerPart[] parts;

   public Computer(){
      parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};      
   }


   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      for (int i = 0; i < parts.length; i++) {
         parts[i].accept(computerPartVisitor);
      }
      computerPartVisitor.visit(this);
   }
}

 Define una interface a representar visitor

public interface ComputerPartVisitor {
    public void visit(Computer computer);
    public void visit(Mouse mouse);
    public void visit(Keyboard keyboard);
    public void visit(Monitor monitor);
}

 Crear un visitor concreto implentando la clase anterior.

public class ComputerPartDisplayVisitor implements ComputerPartVisitor {

   @Override
   public void visit(Computer computer) {
      System.out.println("Displaying Computer.");
   }

   @Override
   public void visit(Mouse mouse) {
      System.out.println("Displaying Mouse.");
   }

   @Override
   public void visit(Keyboard keyboard) {
      System.out.println("Displaying Keyboard.");
   }

   @Override
   public void visit(Monitor monitor) {
      System.out.println("Displaying Monitor.");
   }
}

 Usa el ComputerPartDisplayVisitor a direccionar partes de Computer.

public class VisitorPatternDemo {
   public static void main(String[] args) {

      ComputerPart computer = new Computer();
      computer.accept(new ComputerPartDisplayVisitor());
   }
}


 Hemos terminados con los 23 patrones de diseño más comunes.


No hay comentarios:

Publicar un comentario