domingo, 14 de julio de 2013

Ejemplo Patrón Singleton

Vamos a ver uno de los Patrones mas comunes en desarrollo de software, como he indicado en otras entradas  tal vez muchas veces lo utilizamos sin saber ya que es un patrón muy sencillo de implementar.........de igual forma veremos un ejemplo simple donde podremos ver su aplicación.

Que es?

El Patrón Singleton también se conoce como Instancia única, su objetivo es restringir la creación de objetos  pertenecientes a una clase, de modo que solo se tenga una única instancia de la clase para toda la aplicación, garantizando así un punto de acceso global al objeto creado. 

Para implementarlo, la clase Singleton debe tener un constructor privado que solo sera accedido desde la misma clase, se crea también una instancia privada de la clase, así como un método estático que permita el acceso a dicha instancia de la forma ClaseSingleton.getInstanciaSingleton();

Este patrón es  muy útil cuando necesitamos crear un clase común y global para todo el sistema, donde no nos interese crear varias instancias de la misma, por ejemplo podríamos pensar en una clase conexión que utiliza toda la aplicación, si creamos varias instancias de esta podríamos llenar el heap del sistema con muchos objetos innecesarios que se crean cada vez que instanciamos la clase, por eso restringiendo la creación a un único objeto evitamos problemas de rendimiento y trabajo para el garbage collector...

Otro ejemplo podría ser la creación de un objeto que carga los parámetros de un archivo de propiedades, de esta manera evitaríamos que el sistema lea el archivo cada vez que lo necesite, en vez de eso tan solo llamaríamos al objeto que contiene los parámetros necesarios...

El Problema.

Se solicita generar un historial de los eventos ejecutados por 3 usuarios del sistema, estos eventos se generan cada vez que alguno de los usuarios presiona un botón determinado de un panel de opciones, este historial debe contener la fecha y hora de ejecución del evento, además del usuario y opción presionada.

La Solución.

Como nos piden que se genere un historial  de los eventos ejecutados por los usuarios utilizaremos el patrón Singleton, ya que este historial es general para todos los usuarios del sistema, así crearemos un punto global para la aplicación que permita ir almacenando cada evento generado independientemente de quien lo ejecute.....

La Aplicación.

El sistema es muy simple, se contara con 3 usuarios del sistema definidos por defecto, una ventana principal que permitirá seleccionar alguno de los usuarios y posteriormente cargar una ventana donde el usuario seleccionado podrá ejecutar los eventos disponibles, por ultimo se tendrá una ventana donde podremos ver el histórico de eventos ejecutados en la aplicación.

El sistema se divide en un paquete principal que contiene la clase que ejecuta la aplicación, un paquete de ventanas donde almacenaremos las interfaces graficas de usuario, un paquete vo donde tenemos la clase persona necesaria para el envió de usuarios y por ultimo el paquete singleton que contiene la clase representativa del Patrón.

ClaseLogSingleton.

Este es el eje central de nuestro ejemplo, aquí implementamos el patrón Singleton, en ella creamos una instancia privada de la clase, la cual podrá ser accedida mediante el método getMiLogSingleton(), al ser un método estático, todas las clases que necesiten el objeto Singleton podrán obtenerlo realizando el llamado correspondiente, como declaramos el constructor privado, evitamos que se generen instancias de ella....usamos el atributo "contenido" para almacenar el histórico de los eventos generados.
public class ClaseLogSingleton {

private String contenido;
 
/**objeto Singleton*/
private static ClaseLogSingleton miLogSingleton= new ClaseLogSingleton();

private ClaseLogSingleton(){
 setContenido("Eventos de Usuario\n\n") ;
}
/**
 * @return the miLogSingleton
 */
public static ClaseLogSingleton getMiLogSingleton() {
 return miLogSingleton;
}
/**
 * @return the contenido
 */
public String getContenido() {
 return contenido;
}
/**
 * @param contenido the contenido to set
 */
public void setContenido(String contenido) {
 this.contenido = contenido;
}
}


Clase Principal.

Esta clase obtiene un arreglo de objetos Persona que posteriormente son enviados a la VentanaPrincipal para luego poder definir que usuario ejecutó que evento.......
public class Principal {

public static void main(String[] args) {
 Principal miPrincipal = new Principal();
 PersonaVo[] personas=miPrincipal.crearPersonas();
 VentanaPrincipal miVentanaPrincipal=new VentanaPrincipal(personas);
 miVentanaPrincipal.setVisible(true);
}

private PersonaVo[] crearPersonas() {
 PersonaVo persona1= new PersonaVo();
 persona1.setNombre("Pedro");
 persona1.setDocumento(1);

 PersonaVo persona2= new PersonaVo();
 persona2.setNombre("Pablo");
 persona2.setDocumento(2);

 PersonaVo persona3= new PersonaVo();
 persona3.setNombre("Paco");
 persona3.setDocumento(3);
   
 PersonaVo personas[] = {persona1,persona2,persona3};
 return personas;
 }
}

Clase PersonaVo


Con esta clase usamos el Patrón Vo para poder generar instancias de tipo Persona, no realizaremos ningún tipo de proceso complejo con estos objetos, tan solo dichas instancias van a ser usadas como los usuarios del sistema con los que se ejecutan los eventos.

VentanaPrincipal


Esta Clase permite la construcción de la VentanaPrincipal desde la cual podremos acceder a las opciones del sistema, la ventana presenta un combo de selección donde podemos dependiendo de la opción seleccionada, iniciar con los eventos de cada usuario o consultar el histórico de eventos realizados.

VentanaEventos.

Esta clase nos brinda una ventana que representa el Panel solicitado en el problema inicial, básicamente tenemos 6 botones que hacen el papel de las opciones a ejecutar por el usuario, cuando este presiona algún botón se realiza el llamado al objeto Singleton para almacenar el evento realizado y así ir actualizando el histórico de eventos del sistema.

VentanaLog.


Finalmente tenemos la ventana que nos permite visualizar el histórico de eventos realizados en la ventana de los botones, cada vez que llamamos esta ventana desde la VentanaPrincipal se carga el objeto Singleton creado una única vez, evitando instancias con la misma información. 

Conclusiones.

Como vemos el enfoque del patrón es muy simple, básicamente tenemos que conocer algunos conceptos como el manejo de métodos y variables estáticas, así como los niveles de encapsulamiento y ya podremos aplicar el patrón Singleton en nuestras aplicaciones.

También debemos tener en cuenta que todos los patrones tienen mucho mas para dar y muchas variables giran en torno a ellos, en este caso existen otras variantes del Singleton que lo hacen mucho mas óptimo en cuanto a acceso recurrente y manejo de peticiones, sin embargo en esta entrada no trabajamos dichas variantes ya que solo se quiso enmarcar el concepto inicial.....

Los invito a descargar el ejemplo para un mayor entendimiento ;)


Descarga.

El ejemplo es muy básico y simple, para entenderlo mejor 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 ;) 

46 comentarios:

  1. Gracias por compartir. Excelente blog. Info. muy clara y Útil.

    ResponderEliminar
  2. muchas gracias bro... esta muy bueno.. no conoces algunos patrones para programar aplicaciones en red?

    ResponderEliminar
    Respuestas
    1. Hola gracias por tu comentario y por lo que entiendo tal vez te podría servir el patrón Observer, aunque creería que cualquier patrón se puede adaptar a cualquier aplicación, todo depende de como se desarrolle

      Eliminar
  3. muchas gracias por el post, me sirvio para recordar el funcionamiento del singleton. Claro y sencillo -> singleton jeje

    ResponderEliminar
  4. me sirvió mucho, no lo entendía ,pero ahora si!! gracias!! muy bueno los ejm

    ResponderEliminar
    Respuestas
    1. Hola, muchas gracias a ti por comentar, y fue con mucho gusto ;)

      Eliminar
  5. Excelente post, muy bien explicado

    ResponderEliminar
  6. Excelente articulo, muy claro y entendible.

    Pdt: No encuentro el link de descarga para el ejemplo. :-(

    ResponderEliminar
    Respuestas
    1. Hola Diego, gracias por comentar y el link es el que dice link de descarga de color como rojo....jeje pasa el mouse por sobre el y se debe mostrar....... revisa y me confirmas porfa... (Y)

      Eliminar
    2. mmm ya, yo dandole a donde dice "Descarga" y era "link de descarga" jejeje.

      Gracias.

      Eliminar
  7. Hola, me gusto bastante este blog muy entendible y claro y el ejemplo muy bien diseñado gracias por compartir sus conocimientos

    ResponderEliminar
    Respuestas
    1. Hola, me alegra que te gustara, esa es la intención, que sea fácil de entender, un saludo (Y)

      Eliminar
  8. Muy buena tu explicación! de hecho es de las mejores que he encontrado!! Y que hayas puesto un ejemplo detallado hacen del aporte aun mejor! gracias!!

    ResponderEliminar
    Respuestas
    1. Juan David, con mucho gusto, me alegra que te sirviera ;) Gracias por Agradecer (Y)

      Eliminar
  9. Excelente forma de explicar, ejemplo sin tanto rollo... ahora a demostrarlo en mi examen ^^! muchas gracias!

    ResponderEliminar
    Respuestas
    1. Hola, muchas gracias ;) me alegra q te sirva y espero que pases super bien el examen ;)

      Eliminar
  10. Gracias... estaba un poco perdido pero con tu post aclare todo.. :)

    ResponderEliminar
  11. Gracias amigo.
    me salvaste con muchos de tus post.
    Que patron me recomendarias para programacion android ?
    alguna idea de como decidir que patron usar ?

    ResponderEliminar
  12. Genial Exelente Post

    ResponderEliminar
  13. Cristian con este patron es recomendable hacer un chat por ejemplo?.......Gracias

    ResponderEliminar
  14. Por fin encuentro un ejemplo claro y conciso sobre el uso e implementación del Patrón Singleton... Muchas gracias por tu aporte, me ha sido muy útil...
    Saludos desde Argentina!!!

    ResponderEliminar
  15. Hola Cristian. Tengo una consulta, si tengo la clase Banco, Cliente y Cuenta, donde la clase banco son entidades bancarias, cliente son clientes del banco y la clase cuenta son las cuentas de ahorro etc, que tiene un cliente. A cual de estas clases se debe aplicar Singleton, se lo que significa Singleton instanciar solo una vez a una clase. Lo que no tengo muy claro es en que casos se debe aplicar. En el caso de las clases seria a la clase cuenta??? por favor tu ayuda, para tener claro esta definición.

    ResponderEliminar
  16. Gracias, muy bien explicado y con un ejemplo ejecutable para mostrar

    ResponderEliminar
  17. Gracias, buen ejemplo, tendrás de otros patrones como MVC y Re Factory?

    ResponderEliminar
  18. Gracias, buen ejemplo, tendrás de otros patrones como MVC y Re Factory?

    ResponderEliminar
  19. Buen aporte gracias, solo un detalle: Esta roto el link de descarga!... si puedes arreglarlo por favor, de antemano gracias.

    ResponderEliminar
  20. muy bien gracias tiene muchos ejemplos bien explicados

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

    ResponderEliminar
  22. Muy bien explicado, ahora me surge una duda, si me pidieran una clase donde el limite de instancias sea un numero en especifico ejemplo 3 aplicando el patrón Singleton como se podría llevar acabo?

    ResponderEliminar
  23. Oye no se ve donde se usa la clase singleton

    ResponderEliminar
    Respuestas
    1. Hola, en el enlace de descarga encuentras el codigo para que lo verifiques.

      Eliminar
  24. Hola.
    Muy buena explicacion al igual que las de los demas temas.
    Actualmente tengo una dud sobre este patron, no estoy seguro en que casos en especificos se deberia aplicar, no busco una respuesta como "todo depende de lo que quieras", ya que en efecto es verdad, pero deben haber casos comunes donde se aconseje su uso e implementacion. Gracias de nuevo.

    ResponderEliminar
  25. Hola.
    Muy buena explicacion al igual que las de los demas temas.
    Actualmente tengo una dud sobre este patron, no estoy seguro en que casos en especificos se deberia aplicar, no busco una respuesta como "todo depende de lo que quieras", ya que en efecto es verdad, pero deben haber casos comunes donde se aconseje su uso e implementacion. Gracias de nuevo.

    ResponderEliminar
  26. Es muy útil y lleva mucho tiempo usar aplicaciones para eventos.
    App para Eventos

    ResponderEliminar
  27. La solicitud de eventos es necesaria hoy en día.
    App para Eventos

    ResponderEliminar

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