sábado, 6 de julio de 2013

Ejemplo Patrón Abstract Factory

Siguiendo con la secuencia de entradas sobre patrones de diseño, en esta ocasión realizaremos un ejemplo usando el Patrón Abstract Factory.......... es uno de esos ejemplos simples pero que enmarcan el objetivo del patrón.......




Que es?

Antes que nada debemos saber que existe un patrón llamado Factory el cual permite delegar en una clase la responsabilidad de crear objetos de otras clases, basados en esto Podemos decir que el Abstract Factory es una nueva fase de Factory, Teniendo así una Fabrica de Objetos donde la creación es transparente para la clase que los solicita.

Debemos saber entonces que el patrón Abstract Factory nos brinda una interfaz para crear familias de Objetos relacionados sin tener que especificar sus clases concretas desde la clase cliente (Clase que los solicita)

El problema

Se solicita la creación de diferentes vehículos de transporte (Buses, Busetas y Taxis) sin que se especifique en detalle la forma de su creación.

La solución.

Utilizamos el patrón Abstract Factory para independizar la forma como crearemos los objetos, de esta manera creamos familias de objetos de tipo Vehículo delegando el proceso y sin tener que entrar en detalles desde la clase solicitante.

 

La Aplicación.

Una vez mas trabajamos con un ejemplo simple, veremos una aplicación pequeña que permite al usuario crear  familias de vehículos de 3 tipos diferentes, Buses, Busetas y Taxis, tan solo presentamos unas opciones de selección donde escogeremos que Objeto crear, he internamente  por medio del Patrón de Diseño ejecutamos el proceso de creación....

Con este patrón revivimos Conceptos Básicos de Programación Orientada a Objetos tales como Las Interfaces, métodos Abstractos, Herencia, polimorfismo entre otros (si no los conocen los invito a darles una mirada aquí)... 


En General la Aplicación se divide en Clases Fabricas que permiten hacer el llamado a la creación de Objetos, Interfaces que permiten aplicar conceptos como la Herencia y el Polimorfismo, también contamos con clases Concretas que representan los Objetos que crearán las Fabricas y por ultimo la clase principal que permitirá delegar las solicitudes para iniciar el proceso de creación.... Veamos!!!

Las Interfaces.

Interface Vehiculo.

Esta Interface es común para todos los vehículos de nuestra fabrica, en ella se declaran 2 métodos abstractos que serán comunes para los objetos a crear, sin importar si son Buses, Busetas o Taxis (Sabemos que por regla todos los métodos de una interfaz son abstractos, por ello no es necesario declararlos como tal) 
package interfaces;

/**
 * interfaz donde se establece el codigo del servicio
 * @author chenao
 */
public interface Vehiculo 
{
 public void codigoDeVehiculo();
 public int generarCodigo();
}

Interface VehiculoDeTransporte.

Esta Interface será implementada por las diferentes fabricas de de vehículos de la aplicación, cuenta con el método abstracto crearVehiculo() que será común para cada fabrica y como su nombre lo dice, le permitirá a cada una implementar la lógica para crear sus objetos concretos.
package interfaces;

/**
 * interfaz que establece la creacion de un servicio
 * @author chenao
 */
public interface VehiculoDeTransporte {
 public Vehiculo crearVehiculo();
}

Las Fabricas.

Se componen por la Fabrica de Vehículos Principal que hace el llamado a las fabricas de Objetos Concretos..... estas implementan la interface VehiculoDeTransporte permitiendo crear los vehículos del tipo correspondiente y asignar el respectivo código de creación.....

Clase FabricaDeVehiculos.

Esta clase sera la Fabrica Principal cuenta con un método estático que permitirá la creación de los diferentes tipos de vehículos, aplicamos el concepto de polimorfismo para ejecutar el llamado a la Fabrica correspondiente y crear el objeto concreto solicitado  por el cliente.
package fabricas;

import interfaces.Vehiculo;
import interfaces.VehiculoDeTransporte;

/**
 * Clase que permite la creacion de un servicio 
 * @author chenao
 *
 */
public class FabricaDeVehiculos {
 public static void crearFabricaDeVehiculo(VehiculoDeTransporte factory){
  /**Aplicamos Polimorfismo*/
  Vehiculo objetoVehiculo= factory.crearVehiculo();
  objetoVehiculo.codigoDeVehiculo();
 }
}

Clase FabricaBuses.
package fabricas;
import interfaces.Vehiculo;
import interfaces.VehiculoDeTransporte;

import javax.swing.JOptionPane;

import clases.Bus;

/**
 * Clase que permite la creacion de un objeto Bus
 * @author chenao
 *
 */
public class FabricaBuses implements VehiculoDeTransporte{
  public Vehiculo crearVehiculo() {
  Bus miBus=new Bus();
  miBus.setCodigo(miBus.generarCodigo());
  JOptionPane.showMessageDialog(null, "Se ha creado un nuevo Objeto Bus  ");
  return miBus;
 }
}

Clase FabricaBusetas.
package fabricas;
import interfaces.Vehiculo;
import interfaces.VehiculoDeTransporte;

import javax.swing.JOptionPane;

import clases.Buseta;

/**
 * Clase que permite la creacion de un objeto Buseta
 * @author chenao
 *
 */
public class FabricaBusetas implements VehiculoDeTransporte{
 @Override
 public Vehiculo crearVehiculo() {
  Buseta miBuseta=new Buseta();
  miBuseta.setCodigo(miBuseta.generarCodigo());
 JOptionPane.showMessageDialog(null, "Se ha creado un nuevo Objeto Buseta");
  return miBuseta;
 }
}

Clase FabricaTaxis.
package fabricas;
import interfaces.Vehiculo;
import interfaces.VehiculoDeTransporte;

import javax.swing.JOptionPane;

import clases.Taxi;

/**
 * Clase que permite la creacion de un objeto Taxi
 * @author chenao
 *
 */
public class FabricaTaxis implements VehiculoDeTransporte{
 @Override
 public Vehiculo crearVehiculo() {
  Taxi miTaxi=new Taxi();
  miTaxi.setCodigo(miTaxi.generarCodigo());
  JOptionPane.showMessageDialog(null, "Se ha creado un nuevo Objeto Taxi");
  return miTaxi;
 }
}

Las Clases Concretas.

Representan las clases de las que se instanciarán los objetos de tipo Vehículo (Buses, Busetas y Taxis) así como la clase principal que permite delegar las funcionalidades.....Las clases Bus, Buseta y Taxi Implementan la Interface Vehículo, y cada una permite generar un código aleatorio para identificar el vehículo creado....

Clase Bus.
package clases;
import interfaces.Vehiculo;

import javax.swing.JOptionPane;

/**
 *  clase que establece el codigo del servicio de buses
 * @author chenao
 *
 */
public class Bus implements Vehiculo{
 private int codigo;
 
 public int generarCodigo()
 {
  int codigoBus=(int) (Math.random()*9999);
  return codigoBus;
 }
 public int getCodigo() {
  return codigo;
 }
 public void setCodigo(int codigo) {
  this.codigo = codigo;
 }
 public void codigoDeVehiculo() {
  JOptionPane.showMessageDialog(null,"El Codigo del Bus es : "+getCodigo());
 }
}

Clase Buseta.
package clases;
import interfaces.Vehiculo;

import javax.swing.JOptionPane;

/**
 *  clase que establece el codigo del servicio de busetas
 * @author chenao
 */
public class Buseta implements Vehiculo{
 
 private int codigo;
 public int generarCodigo()
 {
  int codigoBuseta=(int) (Math.random()*9999);
  return codigoBuseta;
 }
 public int getCodigo() {
  return codigo;
 }
 public void setCodigo(int codigo) {
  this.codigo = codigo;
 }
 @Override
 public void codigoDeVehiculo() {
JOptionPane.showMessageDialog(null,"El Codigo de la Buseta es:"+getCodigo());
 }
}

Clase Taxi. 
package clases;
import interfaces.Vehiculo;

import javax.swing.JOptionPane;

/**
 * clase que establece el codigo del servicio de taxis
 * @author chenao
 */
public class Taxi implements Vehiculo{
 private int codigo;
 public int generarCodigo()
 {
  /**Generamos un codigo aleatorio para el taxi*/
  int codigoTaxi=(int) (Math.random()*9999);
  return codigoTaxi;
 }
 public int getCodigo() {
  return codigo;
 }
 public void setCodigo(int codigo) {
  this.codigo = codigo;
 }
 @Override
 public void codigoDeVehiculo() {
  JOptionPane.showMessageDialog(null,"El Codigo del Taxi es : "+getCodigo());
 }
}

Clase Principal. 

Esta clase permite iniciar el sistema, en ella creamos las instancias de Fabricas y mediante un menú de opciones se define y delega que Fabrica inicia el proceso de creación...
package principal;
import javax.swing.JOptionPane;

import fabricas.FabricaBuses;
import fabricas.FabricaBusetas;
import fabricas.FabricaDeVehiculos;
import fabricas.FabricaTaxis;

/**
 * clase principal del aplicativo donde se establecen las instancias 
 * de las fabricas
 * @author chenao
 *
 */
public class Principal {

public static void main(String[] args) 
{
 FabricaBusetas busetas=new FabricaBusetas();
 FabricaTaxis taxi=new FabricaTaxis();
 FabricaBuses buses=new FabricaBuses();
 String cad="",salida;
cad+="Ingrese la opción correspondiente para obtener el codigo del servicio\n";
 cad+="1. Codigo servicio de Taxis\n";
 cad+="2. Codigo servicio de Buses\n";
 cad+="3. Codigo servicio de Busetas\n\n";
 try {
 do {
  try 
     {
  int opcion=Integer.parseInt(JOptionPane.showInputDialog(cad));
  switch (opcion)
  {
  case 1:FabricaDeVehiculos.crearFabricaDeVehiculo(taxi);
   break;
 case 2:FabricaDeVehiculos.crearFabricaDeVehiculo(buses);
   break;
 case 3:FabricaDeVehiculos.crearFabricaDeVehiculo(busetas);
   break;
default:JOptionPane.showMessageDialog(null,"No es un valor de consultavalido");
    break;
   }
  } catch (Exception e) {
 JOptionPane.showMessageDialog(null,"No es un parametro de consulta valido");
  }
 salida=JOptionPane.showInputDialog("Desea consultar otro codigo? S/N");
 
 } while (salida.toUpperCase().equals("S"));
     } catch (Exception e) {
  JOptionPane.showMessageDialog(null,"Bye!!!");
  }
 }
}


Conclusiones.

Y Listo!!! Como vemos  es un Patrón que al principio puede sonar un poco intimidante pero a medida que vamos trabajando con el nos damos cuenta de como podemos sacarle provecho a su aplicación...

Podemos evidenciar también el uso de varios conceptos de programación orientada a objetos siendo los patrones de diseño un gran ejemplo de su aplicación....

Descarga.

Como se mencionó el ejemplo es muy básico y simple, sin embargo les dejo el link de descarga para que lo prueben ;).....está en Eclipse pero si usas NetBeans te interesará esta entrada con un vídeo paso a paso de como abrirlo en el........ [recuerden que es gratis.....nada cuesta opinar, compartir o agradecer :)]

También te podría Interesar. 


¿Hay algo que quieras anexar o comentar sobre esta entrada?  no dudes en hacerlo.....y si te gustó, te invito a compartir y Suscribirte ingresando al botón "Participar en este sitio" para darte cuenta de mas entradas como esta ;)  ;)

24 comentarios:

  1. Entendible explicación de este patrón, me sirvió mucho para mi proyecto. Podrías tratar el tema del patrón M-V-C y explicar como se comunican las clases de estas tres capas con un ejemplo en NetBeans. Gracias.

    ResponderEliminar
    Respuestas
    1. Hola, Gracias por el comentario, te cuento que el MVC tambien lo explico en otro articulo, te invito a visitarlo...
      http://codejavu.blogspot.com/2013/06/ejemplo-modelo-vista-controlador.html

      Los ejemplos estan en Eclipse, lo bueno es que el lenguaje es Java y no tendrias problema en hacer lo mismo usando netbeans, un saludo y espero que te sirva ;)

      Eliminar
    2. Entendido...

      Navegando en el blog encontré el tema minutos después. Gracias por responder.

      Eliminar
    3. Con Gusto, y como te parecio? cualquier cosa me dejas un comentario y lo respondere lo mas pronto posible ;)

      Eliminar
  2. sos un groso flaco, me salvaste jajja posta que me salvaste porque el profesor de la facultad no explica nada, y ahora entiendo, gracias che...

    ResponderEliminar
    Respuestas
    1. jajaja con mucho gusto, esa es la idea, muchas veces nos quedamos con dudas de las clases, suele pasar suele pasar ;) un saludo y gracias por comentar...

      Eliminar
  3. Excelentes ejemplos! Muchas gracias!

    Pero no veo los links de tu código. ¿Deberia estar en la palabra "Descarga"?

    ResponderEliminar
    Respuestas
    1. Hola con gusto, y claro, ahí están en la palabra "Link de Descarga"...... yo lo veo como un enlace de texto vinotinto..........al pasar el mouse no aparece? me confirmas por favor como te sale ;)

      Un Saludo

      Eliminar
  4. Excelente amigo, fue de mucha utilidad. Me salvaste la vida, no tengo como agradecerte.
    Muchas Gracias

    ResponderEliminar
    Respuestas
    1. Hola, me alegra que te sirviera, y claro que tienes como agradecerme jeje suscribete, dale me gusta o +1 y compártelo, de esa manera ayudas a que mas gente pueda acceder a el blog, si te sirvió a ti le puede servir a alguien mas ;) un saludo y gracias por agradecer (y)

      Eliminar
  5. buen ejemplo de como aplicar este patron de diseño.

    ResponderEliminar
    Respuestas
    1. tengo una duda si necesito recuperar la instancia que he creado tendria que modificar el metodo estatico de FabricaDeVehiculos para que devuelva un Vehiculo,pero ahi me devuelve la interfaz

      pero la interfaz la puedo castear hacia su clase mas especifica y usar la instancia que he creado.

      espero darme a explicar y mi pregunta es que si es valida esa modificacion que le hice dentro del patron de diseño?

      Eliminar
  6. Muy bueno el ejemplo, pero tengo una duda veo que cuando implementas los metodos sea para bus buseta o taxi, el codigo es exactamente igual, no sera que se repite mucho codigo? o el patron abstract factory permite hacerlo de este modo?.

    Gracias

    ResponderEliminar
    Respuestas
    1. En realidad si se repite, pero es a modo de ejemplo, no porque el patron lo sugiera asi. Si necesitaramos algo asi de simple y se necesite para varios objetos en particular se podría implementar una sola vez y hacer este objeto reutilizable de esta manera favoreces la alta cohesión y la reusabilidad. El objetivo como tal del abstract factory es crear fabricas que puedan crear productos concretos, ésto con el fin de establecer un alto nivel de abstracción y crear soluciones abiertas a la extensión por si se requieren nuevos productos similares, y cerrado a la modificación.

      Eliminar
  7. HOla , esta muy bueno Cristhian, pero cual seria la estructura del programa en Diagrama? me podrias ayudar?.

    ResponderEliminar
  8. Amigos muchas gracias por compartir siempre, te quería decir si puedes hacer ejemplos con los patrones FACTORY METHOD y BUILDER porfavor...me seria de gran ayuda manoo!!

    ResponderEliminar
  9. Mas claro que el agua !!. Muchisimas gracias por explicar este tema tan importante, llevaba un buen rato tratando de entender este patrón hasta que di con tu blog.

    ResponderEliminar
  10. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  11. Excelente artículo! En especial la implementación! Ya que nos permite crear objectos dinámicamente en tiempo de ejecución! He visto otros ejemplos y todos son representaciones del Factory Method! Muchas gracias!

    ResponderEliminar
  12. tenngo la siguiente duda:

    FabricaBusetas busetas = new FabricaBusetas(); // en esta linea estoy creando una instancia de mi fabrica de busetas

    y fabrica de busetas tiene lo siguiente:

    @Override
    public Vehiculo crearVehiculo() {
    Buseta buseta = new Buseta();
    return buseta;
    }

    entonces solo con el objeto busetas ya tengo acceso a mi clase concreta y su implmentación, entonces no entiendo para que se usa:

    FabricaVehiculos.crearFabricaDeVehiculo(buses);

    ??

    ResponderEliminar
  13. Muy bien explicado! me encanto y me ayudo mucho gracias

    ResponderEliminar

Eres libre de realizar cualquier comentario, desde que pueda ayudar con gusto lo atenderé, y si es un critica, bienvenida sea!!!