Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PRACTICA
CURSO : Diseño de Sistemas de Información.
No. : Práctica No.01.
TEMA : Práctica del Patrón de Diseño Singleton.
DURACIÓN ESTIMADA : 50 minutos aproximadamente.
I. OBJETIVOS
II. IMPLEMENTACIÓN
Conceptos clave
Para implementar el patrón Singleton, tenemos diferentes enfoques, pero todos tienen en
común los siguientes conceptos:
● Un constructor privado para restringir la instanciación de la clase desde otras clases.
● Una variable estática privada de la misma clase la cual es la única instancia de la
clase.
● Un método estático público que retorna la instancia de la clase, este es el punto de
acceso global para que el resto del mundo pueda obtener la instancia de la clase
Singleton.
Inicialización anticipada
La instancia de la clase es creada cuando se carga la clase, es el método más fácil para
crear un Singleton, pero el inconveniente es que la instancia es creada aun cuando la
aplicación cliente no la utiliza.
Universidad Nacional Mayor de San Marcos
Facultad de Ingeniería de Sistemas e Informática
Escuela de Ingeniería de Sistemas
package com.journaldev.singleton;
public class EagerInitializedSingleton {
Si la clase Singleton no utiliza muchos recursos, este es el enfoque para utilizar. Pero muchos
escenarios las clases Singleton son creadas para recursos tales como Sistema de Archivos,
conexiones a Bases de Datos, etc. y nosotros debemos evitar su instanciación hasta que por
lo menos el cliente llame al método getInstance. Además, este método no proporciona
manejo de excepciones.
package com.journaldev.singleton;
public class StaticBlockSingleton {
Tanto este enfoque como el anterior crean la instancia aún antes de ser utilizada y no es la
mejor práctica para utilizar.
Universidad Nacional Mayor de San Marcos
Facultad de Ingeniería de Sistemas e Informática
Escuela de Ingeniería de Sistemas
Inicialización relajada
Este método crea la instancia en el método de acceso global.
package com.journaldev.singleton;
public class LazyInitializedSingleton {
Esta implementación trabaja bien en el caso de un entorno con un solo hilo de ejecución,
pero cuando se implementa dentro de sistema con múltiples hilos puede causar problemas
si varios hilos están dentro de if al mismo tiempo, ya que pueden destruir la instancia y ambos
hilos recibirán diferentes instancias de la clase.
package com.journaldev.singleton;
public class hreadSafeSingleton{
Esto trabaja bien y provee seguridad en la ejecución con hilos, pero reduce la performance
debido al costo asociado con el método sinchronized, el cual sólo necesitamos para los pocos
primeros hilos que puedan crear instancias separadas. Para evitar esta sobrecarga extra
utilizamos el principio de cerradura de doble chequeo (doble checking locking). En este
enfoque el bloque sinchronized es usado dentro de la condición if con un chequeo adicional
para asegurar que sólo una instancia de la clase Singleton sea creada.
{
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
package com.journaldev.singleton;
public class BillPughSingleton {
private BillPughSingleton(){}
package com.journaldev.singleton;
import java.lang.reflect.Constructor;
public class ReflectionSingletonTest {
try {
Constructor[] constructors =
EagerInitializedSingleton.class.getDeclaredConstructors();
for (Constructor constructor : constructors) {
//Below code will destroy the singleton pattern
constructor.setAccessible(true);
instanceTwo =
(EagerInitializedSingleton) constructor.newInstance();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(instanceOne.hashCode());
System.out.println(instanceTwo.hashCode());
}
}
Cuando se ejecuta este ejemplo Usted notará que el hashCode para ambas instancias no es
el mismo, lo que destruye el patrón Singleton. La Reflexión es muy potente y es utilizada en
gran cantidad de frameworks tales como Spring e Hibernate. Revise
https://www.journaldev.com/1789/java-reflection-example-tutorial
package com.journaldev.singleton;
public enum EnumSingleton {
INSTANCE;
La Serialización y el Singleton
A veces en sistemas distribuidos nosotros necesitamos implementar la interfaz Serializable
dentro de la clase Singleton de manera que podamos almacenar su estado en disco y
recuperarlo posteriormente en otro punto en el tiempo. Aquí hay un pequeño Singleton que
implementa la interfaz Serializable.
package com.journaldev.singleton;
Universidad Nacional Mayor de San Marcos
Facultad de Ingeniería de Sistemas e Informática
Escuela de Ingeniería de Sistemas
import java.io.Serializable;
public class SerializedSingleton implements Serializable{
package com.journaldev.singleton;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
SerializedSingleton instanceOne =
SerializedSingleton.getInstance();
ObjectOutput out =
new ObjectOutputStream(new FileOutputStream("filename.ser"));
out.writeObject(instanceOne); out.close();
System.out.println("instanceOne hashCode="+instanceOne.hashCode());
Universidad Nacional Mayor de San Marcos
Facultad de Ingeniería de Sistemas e Informática
Escuela de Ingeniería de Sistemas
System.out.println("instanceTwo hashCode="+instanceTwo.hashCode());
}
}
Si ejecuta este programa podrá ver que el valor de hashCode es distinto para ambas
instancias del Singleton, lo cual destruye el patrón, para solucionar esto necesitamos
proveer la implementación del método readResolve()
Después de esto notará que el hashCode de ambos será el mismo dentro del programa de
prueba.
Lecturas recomendadas
● Java Sincronización
https://www.journaldev.com/1061/thread-safety-in-java
● Java clases internas estáticas de ayuda
https://www.journaldev.com/996/java-inner-class
● Java clases anidadas
https://www.journaldev.com/996/java-inner-class
● Java Reflexión
https://www.journaldev.com/1789/java-reflection-example-tutorial
● Java enum
https://www.journaldev.com/716/java-enum
● Java Serialización
https://www.journaldev.com/927/objectoutputstream-java-write-object-file
● Java Deserialización
https://www.journaldev.com/933/objectinputstream-java-read-object-file
Bibliografía
1. Java Singleton Design Pattern Best Practices with Examples
https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-
examples
2. Simply Singleton
http://www.javaworld.com/article/2073352/core-java/simply-singleton.html