He leído que es posible implementar Singleton
en Java usando un Enum
tal como:
public enum MySingleton {
INSTANCE;
}
Pero, ¿cómo funciona lo anterior? Específicamente, un Object
tiene que ser instanciado. Aquí, ¿cómo se MySingleton
está instanciando? ¿Quién está haciendo new MySingleton()
?
java
design-patterns
enums
singleton
Anand
fuente
fuente
INSTANCE
es igual quepublic static final MySingleton INSTANCE = new MySingleton();
.Respuestas:
Esta,
tiene un constructor vacío implícito. Hazlo explícito en su lugar,
Si luego agregaste otra clase con un
main()
método comoTu verias
enum
los campos son constantes de tiempo de compilación, pero son instancias de suenum
tipo. Y, se construyen cuando se hace referencia al tipo de enumeración por primera vez .fuente
private
modificador no tiene significado para unenum
constructor y es completamente redundante.Un
enum
tipo es un tipo especial declass
.Tu
enum
realmente será compilado a algo asíCuando su código accede por primera vez
INSTANCE
, la claseMySingleton
será cargada e inicializada por la JVM. Este proceso inicializa elstatic
campo anterior una vez (perezosamente).fuente
public enum MySingleton { INSTANCE,INSTANCE1; }
y luegoSystem.out.println(MySingleton.INSTANCE.hashCode()); System.out.println(MySingleton.INSTANCE1.hashCode());
imprime diferentes códigos hash. ¿Significa que se crean dos objetos de MySingleton?enum
constantes de diferencia .En este libro de prácticas recomendadas de Java de Joshua Bloch, puede encontrar explicaciones de por qué debe aplicar la propiedad Singleton con un constructor privado o un tipo Enum. El capítulo es bastante largo, así que resumiéndolo:
Convertir una clase en Singleton puede dificultar la prueba de sus clientes, ya que es imposible sustituir una implementación simulada por un singleton a menos que implemente una interfaz que sirva como su tipo. El enfoque recomendado es implementar Singletons simplemente haciendo un tipo de enumeración con un elemento:
Este enfoque es funcionalmente equivalente al enfoque de campo público, excepto que es más conciso, proporciona la maquinaria de serialización de forma gratuita y ofrece una garantía irrefrenable contra la creación de instancias múltiples, incluso frente a ataques sofisticados de serialización o reflexión.
fuente
Como todas las instancias de enumeración, Java crea instancias de cada objeto cuando se carga la clase, con cierta garantía de que se instancia exactamente una vez por JVM . Piense en la
INSTANCE
declaración como un campo final estático público: Java creará una instancia del objeto la primera vez que se haga referencia a la clase.Las instancias se crean durante la inicialización estática, que se define en la Especificación del lenguaje Java, sección 12.4 .
Por lo que vale, Joshua Bloch describe este patrón en detalle como elemento 3 de Effective Java Second Edition .
fuente
Dado que Singleton Pattern se trata de tener un constructor privado y llamar a algún método para controlar las instancias (como algunos
getInstance
), en Enums ya tenemos un constructor privado implícito.No sé exactamente cómo la JVM o algún contenedor controla las instancias de nuestro
Enums
, pero parece que ya usa un implícitoSingleton Pattern
, la diferencia es que no llamamos agetInstance
, solo llamamos Enum.fuente
Como se ha mencionado, hasta cierto punto, una enumeración es una clase de Java con la condición especial de que su definición debe comenzar con al menos una "constante de enumeración".
Aparte de eso, y que las enumeraciones no pueden extenderse o usarse para extender otras clases, una enumeración es una clase como cualquier clase y la usa agregando métodos debajo de las definiciones constantes:
Accede a los métodos de singleton a lo largo de estas líneas:
El uso de una enumeración, en lugar de una clase, es, como se ha mencionado en otras respuestas, principalmente sobre una instanciación segura de subprocesos del singleton y una garantía de que siempre será solo una copia.
Y, quizás, lo más importante, que este comportamiento está garantizado por la propia JVM y la especificación Java.
Aquí hay una sección de la especificación de Java sobre cómo se evitan varias instancias de una instancia de enum:
Vale la pena señalar que después de la instanciación, cualquier problema de seguridad de subprocesos debe manejarse como en cualquier otra clase con la palabra clave sincronizada, etc.
fuente