Patrón Singleton en Java, con ejemplos
El patrón de diseño "Singleton", que en ingeniería del software es un patrón diseñado para limitar la creación de objetos pertenecientes a una clase.
El proyecto de este post lo puedes descargar pulsando AQUI.
En este tutorial vamos a hablar del patrón de diseño "Singleton«, que en ingeniería del software es un patrón diseñado para limitar la creación de objetos pertenecientes a una clase. El objetivo de este patrón es el de garantizar que una clase solo tenga una instancia (o ejemplar) y proporcionar un punto de acceso global a ella. Este patrón; por ejemplo, suele ser utilizado para las conexiones a bases de datos.
Este patrón se implementa haciendo privado el constructor de la clase y creando (en la propia clase) un método que crea una instancia del objeto si este no existe. Veamos a continuación un ejemplo de este patrón en el que vamos a crear una clase llamada "SoyUnico" con un constructor que va a ser privado y un método llamado 'getSingletonInstance()' que será el encargado de crear una instancia de esta clase si no se ha creado todavía:
public class SoyUnico {
private String nombre;
private static SoyUnico soyUnico;
// El constructor es privado, no permite que se genere un constructor por defecto.
private SoyUnico(String nombre) {
this.nombre = nombre;
System.out.println("Mi nombre es: " + this.nombre);
}
public static SoyUnico getSingletonInstance(String nombre) {
if (soyUnico == null){
soyUnico = new SoyUnico(nombre);
}
else{
System.out.println("No se puede crear el objeto "+ nombre + " porque ya existe un objeto de la clase SoyUnico");
}
return soyUnico;
}
// metodos getter y setter
}
Vemos como al llamar al método 'getSingletonInstance()' pregunta si el atributo 'soyUnico‘ es null o no, y si no lo es lo crea. En el caso de que ya haya sido creado imprimirá un mensaje por pantalla diciéndonos que ya existe un objeto de esa clase.
Vamos a ver como efectivamente nos crea un solo objeto, ejecutando el siguiente código en el que llamamos dos veces el método 'getSingletonInstance()':
public class Main {
public static void main(String[] args) {
SoyUnico ricardo = SoyUnico.getSingletonInstance("Ricardo Moya");
SoyUnico ramon = SoyUnico.getSingletonInstance("Ramón Invarato");
// ricardo y ramon son referencias a un único objeto de la clase SoyUnico
System.out.println(ramon.getNombre());
System.out.println(ricardo.getNombre());
}
}
Como salida a este código tenemos lo siguiente:
Mi nombre es: Ricardo Moya
No se puede crear el objeto Ramón Invarato porque ya existe un objeto de la clase SoyUnico
Ricardo Moya
Ricardo Moya
Vemos como efectivamente cuando no hay un objeto de la clase "SoyUnico«, lo crea y si lo quiere volver a crear, el método nos dice que ya hay otro creado pero le asigna la referencia al objeto, es decir que las variables ‘ricardo’ y ‘ramon’ referencian al mismo y único objeto de la clase «SoyUnico"; tal y como podemos ver al preguntar por el atributo 'nombre' de la clase.
Por último este patrón no quedaría perfectamente implementado si no controlamos la copia (o clone) de los objetos de esta clase; por ello es importante sobrescribir el método ‘clone()', para que cuando se quiera clonar este objeto se lance una excepción. Este método lo sobrescribimos de la siguiente forma:
//Sobreescribimos el método clone, para que no se pueda clonar un objeto de esta clase
@Override
public SoyUnico clone(){
try {
throw new CloneNotSupportedException();
} catch (CloneNotSupportedException ex) {
System.out.println("No se puede clonar un objeto de la clase SoyUnico");
}
return null;
}
Veamos que pasa si intentamos clonar el objeto de la clase "SoyUnico":
public class Main {
public static void main(String[] args) {
SoyUnico ricardo = SoyUnico.getSingletonInstance("Ricardo Moya");
try{
SoyUnico richard = ricardo.clone();
System.out.println(richard.getNombre());
}catch (NullPointerException ex){
ex.printStackTrace();
}
}
}
Vemos que nos lanza una excepción y no nos permite clonar ese objeto.
Mi nombre es: Ricardo Moya
No se puede clonar un objeto de la clase SoyUnico
java.lang.NullPointerException
at Main.Main.main(Main.java:21)
En resumen, en este tutorial se ha puesto un ejemplo muy sencillo para ver el funcionamiento del patrón "Singleton» que es un patrón de diseño muy utilizado (quizás el que más), aplicable en los casos en los que solo queremos tener un único objeto de la clase que implementamos.
«Patrón Singleton en Java, con ejemplos», de Ricardo Moya en jarroba.com, con licencia Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0. Obra registrada en Safe Creative.

Te puede interesar
Patrón Singleton en Python, con ejemplos
En este artículo vamos a describir el patrón singleton en Python que es un patrón que tiene como objetivo garantizar que una clase sólo tenga una instancia.
Cómo adoptar IA en la empresa sin cometer los errores más comunes
Patrones de fracaso y éxito en la adopción de IA, framework de decisión práctico, casos de uso seguros y gobernanza mínima para equipos de desarrollo.
Comentarios (21)
-
Hola.
El patron Singleton está desaconsejado.
Puedes ver alguno de los argumentos aqui
https://medium.com/@mcsee/singleton-el-patr%C3%B3n-del-mal-f3fdab0e16a2-
Gracias Maximiliano.
Correcto, es un patrón desaconsejado, que no prohibido. Siempre recomendamos utilizar otros patrones o soluciones alternativas al código para evitar utilizar Singleton por todos los argumentos que se mencionan.
Sin embargo, en ocasiones no queda otra más que utilizarlo para compartir estados de memoria entre diferentes puntos del código en ciertas arquitecturas por la complicación de pasar estados complejos de una manera rápida y eficaz; por ejemplo, para pasar un objeto complejo en Android, compartir estados entre Activities o Fragments se hace complicado sin un patrón de este tipo (una solución alternativa es inicializar el objeto en cada clase, si el objeto realiza mucho cálculo supone una penalización muy grande tanto en tiempo de proceso como en batería del móvil para algo que ya se tenía calculado y que se puede pasar con un patrón Singleton).
-
Me queda mi duda porque si hago:
public static void main(String[] args) {
SoyUnico ricardo = SoyUnico.getSingletonInstance(«Ricardo Moya»);
SoyUnico ramon = SoyUnico.getSingletonInstance(«Ramon Miers»);
SoyUnico dario = new SoyUnico(«dario»);System.out.println(ramon.getNombre());
System.out.println(ricardo.getNombre());
System.out.println(dario.getNombre());
Si lo hago asi puedo instanciar un objeto sin necesidad de usar el metodo getSingleton osea que podria seguir instanciando….-
Buenas Dardo.
Para prevenir las instancias de una clase se puede hacer privado el constructor.
De cualquier manera, la gracia de usar «getSingletonInstance» es obtener la instancia que previamente existe o crearla si no existe. Si se usa el constructor, siempre se crearía una nueva instancia.
-
-
-
-
-
-
si mando a llamar el método getSingletonInstance, para después mandar los setters con los valores esto no tendría ningún problema, cierto?
-
Es aconsejable utilizar el patrón singleton para un sistema web?
creo que podría generar bloqueos si solo se usa una conexión.
-
Hola! Y feliz Navidad!
Entonces, en realidad si podríamos clonarlo pero estaría conceptualmente mal, no??
Saludos
Agustín
-
Hola Agustín.
La idea del patron singleton es que solo haya un objeto de esa clase. Si lo clonamos obviamente habrá 2 o más objetos con lo cual no tendría sentido utilizar este patrón. No es que conceptualmente este mal, pero haciendo un clone no estarías utilizando este patrón. Normalmente cuando he utilizado este patrón no he implementado la excepción del clone ya que asumo que estoy utilizando ese patrón y no voy a clonar ese objeto, pero lo pongo en este tutorial por si acaso.
Saludos
-


Deja un comentario