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.


miércoles, 4 de mayo de 2016

Patrones de Diseño de Comportamiento Parte 3

19. Observer: También conocido como el patrón "Publish-Subscribe" es un patrón de diseño de comportamiento, que define una relación de uno a muchos de tal manera que cuando un objeto cambia su estado, todos los objetos dependientes son notificados de la actualización automáticamente. Nos permite crear objetos observables que mantienen una lista de observadores y les notifica a éstos de cualquier cambio en su estado, normalmente llamando a uno de sus métodos. Está relacionado con algoritmos de funcionamiento y asignación de responsabilidades a clases y objetos. Esta patrón se conoce como el patrón  de publicación-inscripción o modelo-patrón. Estos nombres sugieren la idea básicas del patrón, que son: el obejto de datos, que se le puede llamar Sujeto a partir  de ahora, contiene atributos mediante los cuales cualquier objeto Observador o vista se puede subscribir a él pasándole una referencia a sí mismo. El sujeto mantiene así una lista de las referencias a sus observadores. Los observadores a su vez están obligados a implementar unos métodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores suscritos los cambios que sufre para que todos ellos tengan la oportunidad  de refrescar el contenido representado. De manera que cuando se produce un cambio en el Sujeto ejecutado, por ejemplo, por alguno de los observadores, el objeto de datos puede recorrer la lista de observadores avisando a cada uno. Este patrón suele observarse en los frameworks de interfaces gráficas orientados a objetos, en los que la forma de capturar los eventos es suscribir listeners a los objetos que pueden disparar eventos. El patrón Observer es la clave del patrón de arquitectura Modelo Vista Controlador(MVC).

Representación UML

Ejemplo
Supongamos que tenemos una clase Producto con un precio y queremos emitir un mensaje en la terminal cuando un producto cambie de precio. Para implementar este patrón Producto debería extender de Observable y otra clase hacer que implemente la interfaz Observer, sin embargo, si no queremos o no podemos hacer que nuestra clase extienda de Observable para no limitarnos en nuestra jerarquía de clases o porque ya extiende de otra podemos usar composición, por otro lado, si no queremos registrar el observador en cada instancia de Producto sino observar cualquier instancia que se cree podemos implementar el Observer de forma estática en la clase Producto. El observable ProductoObservable amplia la visibilidad del método setChanged para poder hacer uso de él usando compocisión, deberemos invocarlo para que los observadores sean notificados. Vamos a ver el código del siguiente ejemplo:

package io.github.picodotdev.blogbitix.patronobserver;

import java.math.BigDecimal;
import java.util.Observable;

public class Producto {

    public class PrecioEvent {
      
        private Producto producto;
        private BigDecimal precioAntiguo;
        private BigDecimal precioNuevo;
      
        public PrecioEvent(Producto producto,  BigDecimal precioAntiguo, 
        BigDecimal precioNuevo) {
            this.producto = producto;
            this.precioAntiguo = precioAntiguo;
            this.precioNuevo = precioNuevo;
        }
      
        public Producto getProducto() {
            return producto;
        }
      
        public BigDecimal getPrecioAntiguo() {
            return precioAntiguo;
        }
      
        public BigDecimal getPrecioNuevo() {
            return precioNuevo;
        }      
    }

    private static final ProductoObservable OBSERVABLE;

    private String nombre;
    private BigDecimal precio;

    static {
        OBSERVABLE = new ProductoObservable();
    }

    public static Observable getObservable() {
        return OBSERVABLE;
    }

    public Producto(String nombre, BigDecimal precio) {
        this.nombre = nombre;
        this.precio = precio;
    }

    public String getNombre() {
        return nombre;
    }

    public BigDecimal getPrecio() {
        return precio;
    }

    public void setPrecio(BigDecimal precio) {
        PrecioEvent event = new PrecioEvent(this, this.precio, precio);

        this.precio = precio;

        synchronized (OBSERVABLE) {
            OBSERVABLE.setChanged();
            OBSERVABLE.notifyObservers(event);          
        }
    }
  
    private static class ProductoObservable extends Observable {
        @Override
        public synchronized void setChanged() {
            super.setChanged();
        }
    }
}

package io.github.picodotdev.blogbitix.patronobserver;

import java.util.Observable;
import java.util.Observer;

import io.github.picodotdev.blogbitix.patronobserver.Producto.PrecioEvent;

public class ProductoObserver implements Observer {

    @Override
    @SuppressWarnings("unchecked")
    public void update(Observable observable, Object args) {
        if (args instanceof PrecioEvent) {
            PrecioEvent evento = (PrecioEvent) args;
            System.out.printf("El producto %s ha cambiado de precio de %s a %s%n",
            evento.getProducto().getNombre(),
            evento.getPrecioAntiguo(), evento.getPrecioNuevo());
        }
    }
}
package io.github.picodotdev.blogbitix.patronobserver;

import java.math.BigDecimal;
import java.util.Observer;

public class Main {
    public static void main(String[] args) {
        Producto p1 = new Producto("Libro", new BigDecimal("3.99"));
        Producto p2 = new Producto("Lector libros electrónico", new BigDecimal("129"));

        Observer o1 = new ProductoObserver();
        Producto.getObservable().addObserver(o1);

        p1.setPrecio(new BigDecimal("4.99"));
        p2.setPrecio(new BigDecimal("119"));
    }
}

20. State: Permitir a un objeto modificar su modificamiento cuando su estado interno cambia. El objeto aparecerá para cambiar su clase. Las ventajas del patrón State son que localiza el comportamiento de un estado específico y divide el comportamiento para diferentes estado es decir el patrón State pone todo el comportamiento asociado con un estado particular en un objeto. Debido a que todo el código de un estado específico está en una subclase de State, los nuevos estados y transiciones pueden ser añadidos fácilmente añadiendo nuevas subclases. Hace las transiciones entre estados explícitas, es decir, cuando un objeto define su estado actual únicamente en términos de datos internos, sus transiciones no tienen una representación explícita. Introducir objetos separados para diferentes estados hace las transiciones más explícitas. Los objetos de los estados pueden ser compartidos, si los objetos de los estados no tienen variables instanciadas, el estado que representan está codificado completamente en su tipo, entonces el contexto puede compartir el objeto del estado. La clase Contexto define la interfaz de interés para los clientes. La clase State define una interfaz para encapsular el comportamiento asociado con un estado particular del contexto. Cada Clase ConcreteState implementa un comportamiento asociado con un estado del contexto.

Representación UML

 Ejemplo

Pero para comprenderlo mejor veamos un sencillo ejemplo  en el que controlamos el estado de un semáforo:

package State;

public class Main
{
    public static void main(String[] args)
    {
         Semaforo objSemaforo = new Semaforo();
        // Muestra el aviso por defecto (verde, no hay alerta)
        objSemaforo.mostrar();
         objSemaforo.setEstado( new EstadoNaranja() );
         objSemaforo.mostrar();
        objSemaforo.setEstado( new EstadoRojo() );
        objSemaforo.mostrar();
    }
}

Semaforo.java (Contexto según el diagrama anterior):

package State;
public class Semaforo
{
    private EstadoSemaforo objEstadoSemaforo;
    // -------------------------------------------
    public Semaforo() {
         this.objEstadoSemaforo = new EstadoVerde();
    }
    // -------------------------------------------
     public void setEstado( EstadoSemaforo objEstadoSemaforo ) {
         this.objEstadoSemaforo = objEstadoSemaforo;
    }
    // -------------------------------------------
     @Override
     public void mostrar() {
        this.objEstadoSemaforo.mostrar();
    }
}

EstadoSemaforo.java (Estado según el diagrama anterior):

Package State;
public abstract class EstadoSemaforo
{
    // Método que deberán crear las clases que hereden de ésta
    public abstract void mostrar();
}

EstadoVerde.java (un EstadoConcreto según el diagrama anterior):

package State;
 public class EstadoVerde extends EstadoSemaforo
{
    public EstadoVerde() {
    }
    // -------------------------------------------
    @Override
     public void mostrar() {
        System.out.println("Luz verde");
    }
}

 EstadoNaranja.java (un EstadoConcreto según  el diagrama anterior):

package State;
 public class EstadoNaranja extends EstadoSemaforo
{
    public EstadoNaranja() {
    }
    // -------------------------------------------
    @Override
     public void mostrar() {
        System.out.println("Luz naranja");
    }
}

 EstadoRojo.java(un EstadoConcreto según el diagrama anterior):

package State;
 public class EstadoRojo extends EstadoSemaforo
{
    public EstadoRojo() {
    }
    // -------------------------------------------
    @Override
     public void mostrar() {
        System.out.println("Luz roja");
    }
}

21. Strategy: Este patrón permite  que el algoritmo a ejecutarse se seleccione en tiempo de ejecución. Este algoritmo proporciona una familia de algoritmos, encapsula cada uno dentro de un objeto y los hace intercambiables. Esto permite que el algoritmo a ejecutarse varíe en función del cliente que lo use. En primer lugar, es mucho más fácil comprender cada uno de los distintos comportamientos si su implementación está encapsulada en distintas clases, y no entrelazada en un único método. Esto permite de forma simple añadir nuevos comportamientos, y eliminar  o modificar los existentes. En los casos en que existan varios objetos cuyo comportamiento sea practicamente el mismo, esto se puede reducir a una única clase que haga uso de distintas estrategias. Esto reduce el uso de subclases y, por tanto, el acoplamiento entre ellas. Las posibles estrategias se ejecutan dentro de un objeto de contexto que se encarga de recuperar la estrategia apropiada para el cliente. Cada una de las estrategias implementa una interfaz que define la firma del método de la estrategia.

Representación UML

Ejemplo: 

Pese a que el ejemplo de nuestro videojuego es bastante ilustrativo, dado que en esta serie de artículos tenemos fijación por los coches, implementateremos el patrón a través de un hipotético módulo de la centralita del vehículo que nos permitirá alternar entre una conducción normal y deportiva. La diferencia entre ambas será simple: mayor consumo, mayor potencia, y mayor velocidad. Podríamos añadir más comportamiento "personalizados", como el endurecimiento de la suspensión, pero con estos dos elementos será suficiente para captar la idea.

public interface ITipoConduccion
{
    string ObtenerDescripcion();
    int ObtenerPotencia(float decilitrosCombustible);
    int ObtenerIncrementoVelocidad(float decilitrosCombustible);
}
 A continuación añadiremos las estrategias en sí, es decir, las clases que implementan la interfaz y dotan de distintos comportamientos que serán seleccionados por el contexto. Habíamos dicho que utilizaríamos dos: conducción normal y conducción deportiva. Por lo tanto, crearemos dos clases que proporcionen distintos comportamientos para los mismos métodos:

public class ConduccionNormal : ITipoConduccion
{
    public string ObtenerDescripcion()
    {
        return "Conduccion Normal";
    }

    public int ObtenerPotencia(float decilitrosCombustible)
    {
        return (int)(decilitrosCombustible * 0.842) + 3;
    }

    public int ObtenerIncrementoVelocidad(float decilitrosCombustible)
    {
        return (int)(decilitrosCombustible * 0.422) + 2;
    }
}
public class ConduccionDeportiva : ITipoConduccion
{
    public string ObtenerDescripcion()
    {
        return "Conduccion Deportiva";
    }

    public int ObtenerPotencia(float decilitrosCombustible)
    {
        return (int)(decilitrosCombustible * 0.987) + 5;
    }

    public int ObtenerIncrementoVelocidad(float decilitrosCombustible)
    {
        return (int)(decilitrosCombustible * 0.618) + 3;
    }
}

Lo siguiente será crear el contexto. Esta clase será la encargada de establecer la conexión entre el cliente y las clases que implementan la estrategía, sustituyendo la clase que la implementa dependiendo del comportamiento esperado. Por lo tanto, se compondrá de una referencia a la interfaz que implementarán las estrategias más un método que permita cambiar de instancia(es decir, una property o un setter de toda la vida). A partir de esta funcionalidad básica, el contexto podrá realizar otras operaciones relacionadas con la estrategia que pretende modelar, como por ejemplo la invocación e sus métodos o la encapsulación del cambio de estrategia.

public class Contexto
{
    // Referencia a la interfaz
    private ITipoConduccion tipoConduccion;

    // Propiedad que establecerá un nuevo tipo de conducción (cambio de estrategia)
    public ITipoConduccion TipoConduccion
    {
        get { return tipoConduccion; }
        set { this.tipoConduccion = value; }
    }

    // Métodos de servicio (invocan los métodos implementados por las estrategias)
    public string ObtenerDescripcion()
    {
        return tipoConduccion.ObtenerDescripcion();
    }

    public int IncrementarVelocidad(float combustible)
    {
        return tipoConduccion.ObtenerIncrementoVelocidad(combustible);
    }

    public int IncrementarPotencia(float combustible)
    {
        return tipoConduccion.ObtenerPotencia(combustible);
    }
}

En realidad, la propia clase el cliente puede actuar como clase de contexto, pero siempre será mejor minimizar el acoplamiento entre las estrategias y las reglas de negocio. De este modo, respetaremos otro de los principios de la orientación a objetos: una clase, una responsabilidad. Para comprobar el funcionamiento de nuestro cliente, bastará con utilizar el siguiente código que hará uso del contexto para cambiar de estrategia en tiempo de ejecución.

public class Vehiculo
{
    private Contexto contexto;

    public Vehiculo()
    {
        contexto = new Contexto();
    }

    public void ConduccionDeportiva()
    {
        ITipoConduccion conduccionDeportiva = new ConduccionDeportiva();
        contexto.TipoConduccion = conduccionDeportiva;
    }

    public void ConduccionNormal()
    {
        ITipoConduccion conduccionNormal = new ConduccionNormal();
        contexto.TipoConduccion = conduccionNormal;
    }

    // Métodos que invocan la funcionalidad implementada por la interfaz
    public void Acelerar(float combustible)
    {
        string descripcion = contexto.ObtenerDescripcion();
        int incrementoVelocidad = contexto.IncrementarVelocidad(combustible);
        int potencia = contexto.IncrementarPotencia(combustible);

        Console.WriteLine("Tipo de conducción " + descripcion);
        Console.WriteLine("Combustible inyectado: " + combustible);
        Console.WriteLine("Potencia proporcionada: " + potencia);
        Console.WriteLine("Incremento de velocidad: " + incrementoVelocidad);
    }
}

Finalmente, el código que invoca a nuestro cliente, que será el siguiente:

public class MainClass{
 public static void Main(string[] args)
  {
    Vehiculo v = new Vehiculo();
    v.ConduccionDeportiva();
    v.Acelerar(2.4f);

    Console.WriteLine("");

    v.ConduccionNormal();
    v.Acelerar(2.4f);

    Console.ReadLine();
  }
}

lunes, 2 de mayo de 2016

Patrones de Diseño de Comportamiento Parte 2


16. Iterator: Provee un mecanismo estándar para acceder secuencialmente a los elementos de una colección; define una interface que declara métodos para acceder secuencialmete a los objetos de una colección. Una clase accede a una colección a través de dicha interface. La motivación de este patrón reside en la gran diversidad de colecciones y algoritmos que existe hoy en día para recorrer una colección. Lo que se busca es acceder a los contenidos de los objetos incluidos sin exponer su estructura. Podemos decir que este patrón nace para poder soportar diversas formas de recorrer objetos y para ofrecer una interfaz uniforme para recorrer distintos tipos de estructuras de agregación.
Se utiliza cuando una clase necesita acceder al contenido de una colección sin llegar a ser dependiente de la clase que es utilizada para implementar a la colección, es decir sin tener que exponer su representación interna. Una clase necesita un modo uniforme de acceder al contenido de varias colecciones. Cuando se necesita soportar múltiples recorridos de una colección. Este patrón debe ser utilizado cuando se requiera una forma estándar de recorrer una colección, es decir, cuando no es necesario que un cliente sepa la estructura interna de una clase. Un cliente no siempre necesita saber si debe recorrer un List o un Set o un Queue y, menos que menos, que clase concreta está recorriendo.

Representación UML


Ejemplo

Comencemos por el principio. Imaginemos que disponemos de una fábrica de Vehículos. Esta  fábrica guarda  un registro pormenorizado de los vehículos que fabrica, que están modelados a través de la siguiente clase:

public class Vehiculo
{
    public string Marca { get; set; }
    public string Modelo { get; set; }
    public DateTime FechaFabricacion { get; set; }
    public double Precio { get; set; }

    public Vehiculo(string marca, string modelo,
        DateTime fechaFabricacion, double precio)
    {
        this.Marca = marca;
        this.Modelo = modelo;
        this.FechaFabricacion = fechaFabricacion;
        this.Precio = precio;
    }

    public string CaracteristicasVehiculo()
    {
        return Marca + " " + Modelo + " fabricado en " +
            FechaFabricacion.ToShortDateString() + " con un precio de " +
            Precio + " euros.\n";
    }
}

Como nuestro ingenieros han sido previsores, han decidido que la estructura de datos en la cual se almacenarán los vehículos implemente una interfaz, a la que llamaremos lRegistroVehículos. Este interfaz definirá las operaciones básicas que se harán sobre el registro, que serán insertan un nuevo vehículo y mostrar información sobre éste (un ejemplo más completo también incluirá métodos para eliminar y modificar, pero nos centraremos de momento en esta funcionalidad básica para no desviarnos del ejemplo):

public interface IRegistroVehiculos
{
    void InsertarVehiculo(string marca, string modelo, double precio);
    Vehiculo MostrarInformacionVehiculo(int indice);
    IIteratorVehiculo ObtenerIterator();
}

 Nuestra fábrica de vehículos posee un sistema de gestión que almacena los vehículos en una estructura de datos agregada, como por ejemplo un ArrayList. Nuestra clase, como podremos imaginar, implementará la interfaz lRegistroVehículos.

public class RegistroVehiculos : IRegistroVehiculos
{
    private ArrayList listaVehiculos;

    public RegistroVehiculos()
    {
        this.listaVehiculos = new ArrayList();
    }

    public void InsertarVehiculo(string marca, string modelo, double precio)
    {
        Vehiculo v = new Vehiculo(marca, modelo, DateTime.Now, precio);
        listaVehiculos.Add(v);
    }

    public Vehiculo MostrarInformacionVehiculo(int indice)
    {
        return (Vehiculo)listaVehiculos[indice];
    }
}
 Hasta ahora hemos creado una clase que contendrá la información sobre los vehículos y otra que contendrá un listado de éstos y será capaz de añadir nuevos vehículos y recuperar un vehículo del cual le pasaremos un índice. Sin embargo, aún no hemos visto ni rastro del patrón Iterator por ningún sitio. Este patrón es, precisamente, la pieza que nos falta para que nuestro modelo esté completo. Si el método MostrarInformacionVehiculo le pasamos un índice mayor que el número de elementos que contenga el ArrayList, lo que obtendremos será una bonita excepción de índice fuera de rango. Una posible solución sería comprobar  dentro del método que el número de elementos menos uno es siempre mayor o igual que el índice pasado como parámetro, pero esto no arreglaría el problema: necesitamos una estructura que sea capaz de iterar sobre la colección e informar al cliente si existen más elementos disponibles. Es hora de implementar un iterador.

public interface IIteratorVehiculo
{
    void Primero();
    Vehiculo Actual();
    Vehiculo Siguiente();
    bool QuedanElementos();
}

public class IteratorVehiculo : IIteratorVehiculo
{
    // Referencia al listado completo
    private ArrayList vehiculos;

    // Almacenaremos el índice en el que se encuentra el iterador
    private int posicionActual = -1;

    // El constructor inyectará el ArrayList en el objeto
    public override IteratorVehiculo(ArrayList listado)
    {
        this.vehiculos = listado;
    }

    // Operación 1: Reinicio del índice, colocándolo en el elemento anterior al primero
   public void Primero()
   {
    this.posicionActual = -1;
   }

   // Operación 2: Acceso al elemento actual
    public Vehiculo Actual()
    {
    // Si no existen elementos, devolveremos null.
    // Si el indice actual es mayor que el mayor indice aceptable, devolveremos null.
    // Si el indice actual es -1, devolveremos null.
    if ((this.vehiculos == null) ||
        (this.vehiculos.Count == 0) ||
        (posicionActual > this.vehiculos.Count - 1) ||
        (this.posicionActual < 0))
        return null;

    // Devolvemos el elemento correspondiente al elemento actual
    else
        return (Vehiculo)this.vehiculos[posicionActual];
    }

    // Operación 3: Acceso al siguiente elemento
   public Vehiculo Siguiente()
   {
    // Si no existen elementos, devolveremos null.
    // Si el indice siguiente es mayor que el mayor indice aceptable, devolveremos null.
    if ((this.vehiculos == null) ||
        (this.vehiculos.Count == 0) ||
        (posicionActual + 1 > this.vehiculos.Count - 1))
        return null;

    // Aumentamos el índice en una unidad y devolvemos ese elemento
    else
        return (Vehiculo)this.vehiculos[++posicionActual];
  }
 
  // Operación 4: Comprobación de si existen elementos en la colección
  public bool QuedanElementos()
   {
    // Devolvemos un booleano que será true si la posición siguiente es
   // menor o igual que el
    // máximo índice aceptable (número de elementos del array - 1).
    return (posicionActual + 1 <= this.vehiculos.Count - 1);
   }

   public IIteratorVehiculo ObtenerIterator()
   {
    return new IteratorVehiculo(listaVehiculos);
    }
}

Hacemos la clase principal.

public class MainClass{
   public static void main(String[] args) throws Exception{
     // Declaramos el registro
IRegistroVehiculos registro = new RegistroVehiculos();

// Insertamos unos cuantos elementos
registro.InsertarVehiculo("Volkswagen", "Polo", 12300);
registro.InsertarVehiculo("Volkswagen", "Golf GTI", 18900);
registro.InsertarVehiculo("Volkswagen", "Passat", 27000);
registro.InsertarVehiculo("Volkswagen", "Scirocco", 32100);
registro.InsertarVehiculo("Volkswagen", "Touareg", 21800);

// Obtenemos el iterator
IIteratorVehiculo iterador = registro.ObtenerIterator();

// Mientras queden elementos
while (iterador.QuedanElementos())
{
    // Obtenemos el siguiente elemento
    Vehiculo v = iterador.Siguiente();

    // Mostramos su contenido
    Console.WriteLine(v.Marca + " " + v.Modelo + " fabricado el " +
 v.FechaFabricacion.ToShortDateString() + " (" + v.Precio + " euros)");
}
  }
}

17. Mediator:  Coordina las relaciones entre sus asociados. Define un objeto que encapsula cómo interactúan un conjunto de objetos. Promueve un bajo acoplamiento al evitar que los objetos se refieran unos a otros explícitmente, y permite variar la interección entre ellos de forma independiente.
El patrón Mediator coordina las relaciones entre sus asociados. Permite la interacción de varios objetos, sin generar acoples fuertes en esas relaciones. Cuando muchos interactúan con otros objetos, se puede formar una estructura muy compleja, con objetos con muchas conexiones con otros objetos. En un caso extremo cada objeto puede conocer a todos los demás objetos. Para evitar esto el patrón Mediator encapsula el comportamiento de todo un conjunto de objetos en un solo objeto. Un conjunto grande de objetos se comunica de una forma bien definida, pero compleja. Reutilizar un objeto se hace difícil por que se relaciona con muchos objetos. El comportamiento de muchos objetos que está distribuido entre varias clases, puede resumirse en una o varias por subclasificación.

Representación  UML


 Ejemplo

Crear clase Mediator
import java.util.Date;

public class ChatRoom {
   public static void showMessage(User user, String message){
      System.out.println(new Date().toString() + " [" + user.getName() + "] : " + 
message);
   }
}
Crear clase usuario

public class User {
   private String name;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public User(String name){
      this.name  = name;
   }

   public void sendMessage(String message){
      ChatRoom.showMessage(this,message);
   }
}
 
Usa el objeto User a mostrar comunicación entre ellos.

public class MediatorPatternDemo {
   public static void main(String[] args) {
      User robert = new User("Robert");
      User john = new User("John");

      robert.sendMessage("Hi! John!");
      john.sendMessage("Hello! Robert!");
   }
}

18. Memento: Este patrón de diseño permite capturar y exportar el estado interno de un objeto para que luego se pueda restaurar; sin romper la encapsulación. Su finalidad es almacenar el estado de un objeto (o del sistema completo) en un momento dado, de manera que se pueda restaurar posteriormente si fuese necesario. Para ello se mantiene almacenado el estado del objeto para un instante de tiempo en una clase independiente de aquella a la que pertenece el objeto(pero sin romper la encapsulación), de forma que ese recuerdo permita que el objeto(pero sin romper la encapsulación), de forma que ese recuerdo permite que el objeto sea modificado y pueda volver  a su estado anterior. Hoy en dia, muchos aplicativos permiten el "deshacer" y "rehacer" de manera muy sencilla. Para ciertos aplicativos es casi una obligación tener estas funciones y sería impensado el hecho que no las posean. Sin embargo, cuando queremos llevar esto a código puede resultar complejo de implementar. Este patrón intenta mostrar una solución a este problema. Se usa cuando se necesite restaurar el sistema desde estados pasados, además se quiera facilitar el hacer y deshacer de determinadas operaciones, para que lo que habrá que guardar los estados anteriores de los objetos sobre los que opere (o bien recordar los cambios de forma incremental). Este patrón debe ser utilizado cuando se necesite salvar el estado de un objeto y tener disponible los distintos estados históricos que se necesiten. Por ello mismo, este patrón es muy intuitivo para darse cuando debe ser utilizado.

Representación  UML


 Ejemplo

Crear clase Memento

public class Memento {
   private String state;

   public Memento(String state){
      this.state = state;
   }

   public String getState(){
      return state;
   }  
}
Crear clase Originator

public class Originator {
   private String state;

   public void setState(String state){
      this.state = state;
   }

   public String getState(){
      return state;
   }

   public Memento saveStateToMemento(){
      return new Memento(state);
   }

   public void getStateFromMemento(Memento Memento){
      state = Memento.getState();
   }
}

Crear  la clase CareTaker

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

public class CareTaker {
   private List<Memento> mementoList = new ArrayList<Memento>();

   public void add(Memento state){
      mementoList.add(state);
   }

   public Memento get(int index){
      return mementoList.get(index);
   }
}
 Usar objetos CareTaker y  Originator.

public class MementoPatternDemo {
   public static void main(String[] args) {
 
      Originator originator = new Originator();
      CareTaker careTaker = new CareTaker();
    
      originator.setState("State #1");
      originator.setState("State #2");
      careTaker.add(originator.saveStateToMemento());
    
      originator.setState("State #3");
      careTaker.add(originator.saveStateToMemento());
    
      originator.setState("State #4");
      System.out.println("Current State: " + originator.getState());      
    
      originator.getStateFromMemento(careTaker.get(0));
      System.out.println("First saved State: " + originator.getState());
      originator.getStateFromMemento(careTaker.get(1));
      System.out.println("Second saved State: " + originator.getState());
   }
}