Programando o Intentándolo

Patrón Singlenton en Java

El patrón singlenton es de los patrones de diseño más sencillos tanto porque esta muy claro cual es su objetivo como por lo sencilla que resulta su implementación.

Mediante este patrón podemos hacer que únicamente haya una sola instancia de una clase en nuestra aplicación de forma similar a una variable global pero de una forma más elegante.

Este patrón es ampliamente utilizado ya que hay multitud de ocasiones en las que se necesita que necesita compartir alguna información en la aplicación, tener un único punto de acceso a un recurso o cualquier situación en la que se necesite tener un solo objeto de una clase.

Una vez visto un poco para que se usa el patrón singlenton vamos a ver como se realiza su implementación en java:

El código habla por si solo pero vamos a explicarlo línea por línea:

  • El primer paso es crear en la propia clase un objeto de la propia clase, que será la única instancia de nuestra clase.
  • Para impedir que se puedan crear nuevas instancias de nuestra clase tenemos que declarar el constructor de nuestra clase como privado para evitar que se pueden crear objetos desde fuera desde nuestra clase.
  • Finalmente el ultimo paso es declarar un método publico para obtener el objeto que hemos creado en un primer momento y de esta forma dotar de una forma de acceso a la única instancia de nuestra clase.

Así de sencillo es implementar el patrón singlenton en java, hay algunas pequeñas variantes posibles como inicializar el objeto dentro de un método en lugar de hacerlo en la declaración pero si se hace de este modo no hay que olvidar que a la hora de comprobar si ya hay alguna instancia creada hay que hacerlo de forma sincronizada porque si se da el caso de que se hacen varias llamadas simultaneas cuando aun no se ha creado ninguna instancia puede suceder que se cree más de una instancia con lo que habremos fallado en nuestro intento de que solo haya una instancia de nuestra clase.

A continuación pongo el ejemplo de como no se debe de hacer porque podrían crearse varias instancias y aunque ciertamente no es que este mal, si que es cierto que solo es valido para aplicaciones en las que hay un solo hilo de ejecución, pues aunque sea improbable que se creen varias instancias puesto que solo podría suceder en el momento en el que aun no hay ninguna y que además en ese momento se produjesen varias llamadas al método getInstance() siempre se deben tener en cuenta estos casos para evitar fallos en nuestras aplicaciones.

La forma “correcta” para el código anterior sería la siguiente:

La esencia es la misma que la del código anterior pero la comprobación de si ya se ha creado un objeto de nuestra clase se hace dentro de un método sincronizado por lo que nos aseguramos de que solo pueda haber una instancia de nuestra clase.

Para terminar voy a poner un ejemplo de uso del patrón singlenton un poco peculiar pero que creo que permite ver perfectamente como funciona este patrón y la diferencia entre utilizarlo y no hacerlo.

El ejemplo que propongo es hacer una clase que simule un reloj, es decir, que nos vaya dando la hora cada segundo (para hacerlo sencillo simplemente haremos una aplicación de consola en la que imprimiremos la hora por pantalla cada segundo) y el reloj se va a crear usando el singlenton porque no tiene sentido tener varias instancias distintas porque todas nos darían la misma hora y además al hacerlo como una aplicación de consola si creamos más de un objeto de la clase reloj se nos imprimiría cada hora tantas veces como instancias de la clase reloj hubiésemos creado previamente.

El código es sencillo, pero como la clase Reloj además de implementar el patrón Singlenton también crea un hilo de ejecución que se encargue de imprimir la hora cada segundo sin bloquear el hilo principal por si quisiésemos hacer alguna otra tarea mientras tanto hay que inicializar el thread en el momento en el que se inicializa el reloj dentro del método createInstance() porque el hilo solo hay que inicializarlo una sola vez.

Y para crear un reloj en lugar de hacer un new Reloj(), que no podemos hacer porque hemos declarado el constructor como privado tenemos que hacer uso del método getInstancia() y para ver que aunque intentemos crear varias instancias solo se crea intentamos crear 3 relojes.

Tanto en la clase Main como en la clase Reloj hay algunas líneas comentadas por si quieres probar que sucede si no usamos el patrón singlenton y ver las diferencias.

Finalmente, si quieres este ultimo proyecto de ejemplo puedes descargar el código completo desde aquí.