Java Singleton el patrón de diseño más básico . Como ya he comentado en varias ocasiones el conocimiento de los patrones de diseño es algo clave a la hora de abordar desarrollos y de solucionar problemas, sobre todo problemas complejos y que necesitan flexibilidad .Hoy voy a entrar a detalle en uno de los patrones de diseño mas sencillo ,el patrón Java Singleton . Este patrón de diseño se encarga de que una clase determinada únicamente pueda tener un único objeto. Normalmente una clase puede instanciar todos los objetos que necesite.
Singleton y Limitaciones
Sin embargo una clase que siga el patrón Singleton tiene la peculiaridad de que solo puede instanciar un único objeto .Este tipo de clases son habituales en temas como configurar parámetros generales de la aplicación ya que una vez instanciado el objeto los valores se mantienen y son compartidos por toda la aplicación. Uno de los ejemplos más clásicos son las clases que Spring instancia que todos son Singleton por defecto. Vamos a construir una clase con un Java Singleton. A esta clase la denominaremos configurador.
Java Singleton
Una vez que tenemos claro cual es el concepto de Configurador vamos a crearlo en código .En este caso nuestro configurador almacenará dos valores url, y base de datos que serán compartidos por el resto de Clases de la aplicación , las cuales simplemente la leerán.
package com.arquitecturajava; public class Configurador { private String url; private String baseDatos; private static final Configurador miconfigurador; public static Configurador getConfigurador(String url, String baseDatos) { if (miconfigurador == null) { miconfigurador = new Configurador(url, baseDatos); } return miconfigurador; } private Configurador(String url, String baseDatos) { this.url = url; this.baseDatos = baseDatos; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getBaseDatos() { return baseDatos; } public void setBaseDatos(String baseDatos) { this.baseDatos = baseDatos; } }
Para conseguir que una clase sea de tipo Singleton necesitamos en primer lugar que su constructor sea privado. De esa forma ningún programa será capaz de construir objetos de esta tipo y por lo tanto no podremos construir ninguno estaremos en cero . En segundo lugar necesitaremos disponer de una variable estática privada que almacene una referencia al objeto que vamos a crear a traves del constructor . Por ultimo un método estático publico que se encarga de instanciar el objeto la primera vez y almacenarlo en la variable estática apoyándose en el constructor privado que recordemos se puede llamar desde la misma clase.
Una vez aclarado como funciona un Singleton es muy sencillo utilizarle desde un programa ya que basta con invocar al método estático.
package com.arquitecturajava; public class Principal { public static void main(String[] args) { Configurador c = Configurador.getConfigurador("miurl", "mibaseDatos"); System.out.println(c.getUrl()); System.out.println(c.getBaseDatos()); } }
Singleton y ClassLoaders
A veces los patrones pueden sernos muy útiles y a veces pueden no serlo tanto y llevarnos a situaciones problemáticas . Por ejemplo si preguntamos lo siguiente . ¿El patrón Singleton nos genera un único objeto para una clase Java? . La respuesta mas normal es “SI” sin embargo esta no es verdad del todo. La respuesta correcta es que el patron Singleton nos genera un objeto por cada clase cargada en el mismo ClassLoader.¿ Que quiere decir esto?. Pues quiere decir que por ejemplo dos aplicaciones web que cada una tiene su propio WebClassLoader tendrán cada una so propia instancia.
Esto en principio no es problemático porque se encuentran aisladas . Ahora bien hay situaciones en las que un administrador de sistemas puede decidir compartir librerias y clases entre distintas aplicaciones.
En este caso si podemos tener problemas ya que el objeto Singleton que en principio fue diseñado para configurar una aplicación concreta estará compartido por varias. Mucho ojo sobre como gestionamos este patrón de diseño ya en algunos casos puede generar problemas y situaciones curiosas .
Perdona, pero una variable final no se puede reasignar, he copiado tu código en eclipse y da error, uno, porque no está inicializada, me refiero a miConfigurador y dos porque no puedes hacer un new() sobre algo que es final, no puedes reasignarlo
una consulta se puede usar el patrón SINGLETON para crear una clase que ejecute una tarea programada dentro de una aplicación web, independiente del usuario que se loguea??
Si mientras sea información que no es particular de nadie , no hay problema
en una aplicacion de escritorio q se ejecuta mas de una vez es aplicable el singleton de esta manera? ejemplo mi aplicacion procesa archivos y la lanzo para procesar 100 archivos antes de q termine la lanzo de nuevo para ´´´´procesar otros 100 (los 100 primeros no deben ser tocados por la segunda ejecucion) es posible hacerlo a partir de un singleton??
Podrias almacenarlo en algun tipo de hashmap en el singleton
Hola!, me ha resultado interesante este aporte, he estado investigando un poco acerca de los diseños de patrón, solo me ha asaltado una duda, ¿Qué aplicaciones web son ejemplos de este tipo patrón?
Saludos ! 😀
Lo usan a veces para cargar datos en memoria perpetuos
Gracias por el aporte y como siempre la rigurosidad de nuestros colegas se deja notar en los comentarios. Estoy seguro de que eres consciente de todo lo que indican, quizás si en el artículo pusiera una pequeña indicación del tipo “Fundamentos del Singleton” jejeje se queda más tranquilos.
Siempre hay opciones 🙂 . Pero un articulo posicionado es mejor no moverlo
Hola.
Una observación, como buena practica la variable estática el el singleton se debe declarar final, esto evita que se pueda cambiar el objeto.
private static final Configurador CONFIGURADOR;
gracias por el aporte 🙂
Hola,
Si vas a declarar final la variable estática, no se puede hacer miconfigurador=new Configurador(url,baseDatos); (Linea 13). Ya que se debe inicializar en la misma linea de la declaración o en un bloque estático. El código del ejemplo no compila.
Saludos!
gracias por el aporte
[…] Otros artículos relacionados: Patrón Factoría , Patrón Singleton […]
En el párrafo segundo del apartado titulado ‘Java Singleton’ se dice textualmente que “En segundo lugar necesitaremos disponer de una variable estatica privada que almacene una referencia al objeto que vamos a crear a traves del constructor”. Y, en mi opinión, es una afirmación errónea. Es cierto que se necesita una variable estática privada que almacene una referencia al objeto que vamos a crear, pero ese objeto no se crea en el constructor de la clase – ‘private Configurador(String url,String baseDatos)’ – sino en el método estático público destinado a instanciar el objeto la primera vez y almacenarlo en la… Read more »
Me surgio una duda, si donde tu dices que el objeto se crea en el metodo estatico publico entonces por que razon debe llamar al constructor ? existe una manera de crear un objeto sin involucrar al constructor?
para inicializar lo que necesites , y generar una instancia , no queda otra , podrias usar sino el constructor por defecto y métodos set
.-Ingresar 10 valores, mostrar el mayor y menor
Ingresa valores:
5
4
6
7
12
56
10
11
8
13
Mayor: 56
Menor: 4
ayudenme pliss
ArrayList array=new ArrayList();
array.add(5);
array.add(4);
array.add(6);
array.add(7);
array.add(12);
array.add(56);
array.add(10);
array.add(11);
array.add(8);
array.add(13);
System.out.println(Collections.max(array));
System.out.println(Collections.min(array));
Estimato Cecilo
Deseo saber como puedo hacer una app web en java que me permita hacer la instalacion de modulos, similar a como lo hace OpenErp, de antemano te agradesco por tu tiempo prestada a la misma.
Si me recomiendas algun libro, o algun blog estaria encantado
No me conozco openERP pero igual te estas refiriendo al concepto de portlet? , en ese caso liferay es un buen gestor de portales java
[…] esta forma ganaremos en claridad en cuanto al diseño se refiere. Otros artículos relacionados : Java Singleton Pattern , Java FlyWeight CQR Martin […]
¿Esta implementación de singleton es “thread safe”? 2 hilos pueden acceder de forma concurrente al if y entonces tendríamos 2 instancias y no 1.
Serlo no lo sería pero al ser la variable estática solo una instancia quedaría guardada. Si uno necesita más debería definir los métodos como syncronized
excelemte aporte, justo para mi clase de Ingenieria de software jeje (Y)
me alegro que te sea de utilidad 🙂
[…] artículos relacionados: Singleton ClassLoaders ,Spring Singleton vs Prototype , EJB […]
IDEM ANTERIORES COMENTARIOS. ME GUSTARÍA CONOCER EL POR QUÉ? SE UTILIZA EL FORMATO DE ESTRUCTURAS Y MÉTODOS [QUE ME SON UN POCO EXTRAÑOS ] PARA REALIZAR UNA APLICACIÓN Y SI CAMBIAN ÉSTOS MODELOS SEGÚN LA APLICACIÓN. GRACIAS.
Acabo de escribir un artículo en el blog que espero te sea de ayude 🙂 . Gracias por la idea 😉
Excelente ejemplo, gracias, me gustaría [como principiante] conocer algo de las estructuras y métodos utilizados [el por qué?], para poder construir por ejemplo una calculadora o algún singleton de bajo nivel. NUEVAMENTE GRACIAS.
Excelente ejemplo, quedo claro en la primera lectura . Gracias
me alegro te haya sido util 🙂
[…] artículos relacionados: Singleton , […]
Un detalle respecto al patrón Singleton, un poco ya a más bajo nivel. Como comenta Josua Bloch en su libro Effective Java, la mejor forma de implementar este patrón es utilizando un Enum (aunque sea un idiom bastante desconocido). Un enum te proporciona directamente Thread Safety y serialización, mientras que la alternativa de declarar un constructor privado y usar un getInstance() puede presentar problemas en entornos concurrentes (habría que aplicar double checked locking) y en casos de serialización/deserialización. Por último, comentar que si bien el patrón Singleton es uno de los más conocidos, desde hace algún tiempo existen corrientes que… Read more »
Gracias por el aporte :). Tienes mucha razón
Cecilio, al getInstance le falta la sincronización para asegurar que realmente sea una única instancia (y dependiendo de lo que uno quiera hacer hasta se le pueden poner 2 puntos de sincronización)
Saludos
puse getInstance y es getConfigurador
🙂
Si en el caso de que cuando se construya el singleton varios thread pudieran acceder a el podriamos tener problemas de sincronismo :). Prefiero dejarlo así por simplicidad pero gracias por el aporte
Muy buen ejemplo y explicado de forma clara y concisa como siempre. Solo una cosa, al método getConfigurador le falta la palabra clave “static”.
Enhorabuena por el blog!
gracias lo correguire 🙂
una consulta al compilar el programa que datos se colocan ?
Si lo vuelves a compilar pues empezará de nuevo todo
Muy claro el patron Singleton !
gracias 🙂