Implementación de Singleton con una enumeración (en Java)
He leído que es posible implementar Singleton
en Java usando algo Enum
como:
public enum MySingleton {
INSTANCE;
}
Pero, ¿cómo funciona lo anterior? Específicamente, Object
se debe crear una instancia de an. Aquí, ¿cómo se MySingleton
crea una instancia? ¿ Quién está haciendo new MySingleton()
?
Este,
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 agregaste otra clase con un main()
método como
public static void main(String[] args) {
System.out.println(MySingleton.INSTANCE);
}
Tu verias
Here
INSTANCE
enum
Los campos son constantes de tiempo de compilación, pero son instancias de su enum
tipo. Y se construyen cuando se hace referencia al tipo de enumeración por primera vez .
Un enum
tipo es un tipo especial de class
.
En realidad , serás enum
compilado en algo como
public final class MySingleton {
public final static MySingleton INSTANCE = new MySingleton();
private MySingleton(){}
}
Cuando su código acceda por primera vez INSTANCE
, MySingleton
la JVM cargará e inicializará la clase. Este proceso inicializa el static
campo anterior una vez (perezosamente).
En este libro de mejores prácticas de Java de Joshua Bloch, puede encontrar una explicación de por qué debería aplicar la propiedad Singleton con un constructor privado o un tipo Enum. El capítulo es bastante largo, por lo que lo resumiré:
Hacer que una clase sea Singleton puede dificultar la prueba de sus clientes, ya que es imposible sustituir un singleton por una implementación simulada a menos que implemente una interfaz que sirva como su tipo. El enfoque recomendado es implementar Singletons simplemente creando 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 proporciona una garantía sólida contra la creación de instancias múltiples, incluso frente a ataques sofisticados de serialización o reflexión.
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.
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 crea una 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 si sirve de algo, Joshua Bloch describe este patrón en detalle como el elemento 3 de Effective Java Second Edition .