Patrón Singleton en Java
En esta entrada vamos a ver en qué consiste y cómo crear un Patrón Singleton en Java, el cual es uno de los patrones más usados en nuestros desarrollos y pertenece a la familia de los patrones creacionales . Aunque no seamos consciente de su uso, es usado en los frameworks de Java como Spring, Quarkus, Micronaut etc…
¿Qué es el Patrón Singleton?
El Patrón Singleton se basa en la creación de una instancia única, este patrón se realiza para evitar restringir la creación de objetos de una clase. De esta manera podemos asegurar y garantirzar que una clase únicamente tiene una instancia creada.
Por ejemplo, Spring Framework usa por defecto el Scope Singleton, con lo que garantiza que una única instancia es devuelta. Es decir, asegura que todas las peticiones que se hagan a ese bean siempre devuelven el mismo objeto.
El uso de este tipo de clases suele ser normal y habitual encontrarlo cuando queremos realizar configuraciones generales de la aplicación, ya que una vez instanciado, el objeto se mantiene y puede ser compartido por toda la aplicación.
¿Cómo implementar el Patrón Singleton?
Para implementar el Patrón Singleton se necesitan al menos los 3 elementos siguientes:
- Un constructor privado: Evitamos que se creen por terceros ejecuciones.
- Un campo estático que contiene su única instancia: Referencia al objeto que vamos a crear a traves del constructor.
- Un método estático público para poder obtener la instancia: Instancia el objeto la primera vez y lo almacena en la variable estática.
Una aproximación de la implementación de una clase Singleton podría ser la siguiente:
public final class Singleton { private static Singleton SINGLETON_INSTANCE; private Singleton() { } public static Singleton getSingletonInstance() { if(SINGLETON_INSTANCE == null) { SINGLETON_INSTANCE = new Singleton(); } return SINGLETON_INSTANCE; } // getters and setters }
Problemas con Patrón Singleton
Patrón Singleton y Thread Safe
Uno de los problemas que tiene la implementación del Patrón Singleton, visualizado arriba es que no es Thread Safe, lo que quiere decir, que no funciona correctamente en entornos multithread. En entornos de un único threads, el funcionamiento es correcto, y cuando vayamos a entornos de uso de varios threads tendremos que añadir el uso de synchronized:
public synchronized static Singleton getSingletonInstance() { if (SINGLETON_INSTANCE == null) { SINGLETON_INSTANCE = new Singleton(); } return SINGLETON_INSTANCE; }
El uso de synchronized se debe a que de esta manera evitamos que dos threads entren a la vez en el método y puedan crear de manera simultánea un objeto y tener dos instancias del mismo objeto.
Por otro lado, hay que tener en cuenta que el uso de synchronized penaliza el rendimiento, por lo que si es necesario su uso habría que ver diferentes maneras de mejorar el rendimiento como lazy initialization o double checked locking, con este último moveremos el bloque synchronized dentro del método y haremos una verificación previa.
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){ if(instance == null){ synchronized (ThreadSafeSingleton.class) { if(instance == null){ instance = new ThreadSafeSingleton(); } } } return instance; }
ClassLoaders con Patrón Singleton
Una aplicación con un objeto Singleton nos generará un único objeto en su ClassLoader. Entonces, ¿qué pasa si tenemos dos aplicaciones con un WebClassLoader por cada una?, pues que cada una tendrá su propia instancia del objeto. Esto en un principio sería lo correcto, pero si compartimos librerías entre las distintas aplicaciones podríamos empezar a tener problemas.
Conclusión
El patrón singleton en Java es un patrón imprescindible de conocer y entender cuando trabajamos y desarrollamos con Java en diferentes frameworks.
Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!
1 pensamiento sobre “Patrón Singleton en Java”