thread safe patterns pattern journaldev example enum java design-patterns enums singleton

safe - journaldev java design patterns



ImplementaciĆ³n de Singleton con una enumeraciĆ³n(en Java) (6)

Como se ha mencionado hasta cierto punto antes, un enum es una clase java con la condición especial de que su definición debe comenzar con al menos una "constante enum".

Parte de eso, es una clase como cualquier clase y la usas agregando métodos debajo de las definiciones constantes:

public enum MySingleton { INSTANCE; public void doSomething() { ... } public synchronized String getSomething() { return something; } private String something; }

Accede a los métodos de singleton a lo largo de estas líneas:

MySingleton.INSTANCE.doSomething(); String something = MySingleton.INSTANCE.getSomething();

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 del hilo 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:

Un tipo de enumeración no tiene instancias distintas de las definidas por sus constantes de enumeración. Es un error en tiempo de compilación intentar crear una instancia explícita de un tipo de enumeración. El método de clonación final en Enum asegura que las constantes enum nunca se puedan clonar, y el tratamiento especial por el mecanismo de serialización asegura que nunca se creen instancias duplicadas como resultado de la deserialización. Se prohíbe la creación de instancias reflexivas de tipos de enumeración. Juntas, estas cuatro cosas aseguran que no existan instancias de un tipo enum más allá de las definidas por las constantes 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.

He leído que es posible implementar Singleton en Java usando una Enum como:

public enum MySingleton { INSTANCE; }

Pero, ¿cómo funciona lo anterior? Específicamente, un Object tiene que ser instanciado. Aquí, ¿cómo se está instanciando MySingleton ? ¿Quién está haciendo new MySingleton() ?


Como todas las instancias de enumeración, Java crea una instancia de cada objeto cuando se carga la clase, con cierta garantía de que se instancia exactamente una vez por JVM . Piense en la declaración INSTANCE 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 .

Para lo que vale, Joshua Bloch describe este patrón en detalle como elemento 3 de Effective Java Second Edition .


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 nuestras Enums , pero parece que ya usa un Singleton Pattern implícito, la diferencia es que no llamamos a getInstance , solo llamamos a Enum.


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:

// Enum singleton - the preferred approach public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }

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 ante ataques de reflexión o serialización sofisticados.

Si bien este enfoque aún no se ha adoptado ampliamente, un tipo de enumeración de un solo elemento es la mejor manera de implementar un singleton.


Esta,

public enum MySingleton { INSTANCE; }

tiene un constructor vacío implícito. Hazlo explícito en su lugar,

public enum MySingleton { INSTANCE; private MySingleton() { System.out.println("Here"); } }

Si luego agregó otra clase con un método main() como

public static void main(String[] args) { System.out.println(MySingleton.INSTANCE); }

Tu verias

Here INSTANCE

enum campos enum son constantes de tiempo de compilación, pero son instancias de su tipo enum . Y, se construyen cuando se hace referencia al tipo de enumeración por primera vez .


Un tipo de enum es un tipo especial de class .

Su enum se compilará en algo así como

public final class MySingleton { public final static MySingleton INSTANCE = new MySingleton(); private MySingleton(){} }

Cuando su código accede por primera vez a INSTANCE , la clase MySingleton será cargada e inicializada por la JVM. Este proceso inicializa el campo static anterior una vez (perezosamente).