patrones - java factory pattern
¿Es el Enlet Type Singleton de un solo elemento realmente una buena idea ampliamente adoptada? (5)
(Esta respuesta supone que un singleton "forzado" es realmente lo que usted quiere, a diferencia de un singleton de facto administrado por su marco DI (por ejemplo, @Singleton
de Guice), que probablemente sea la idea más frecuente).
Para descomponer su pregunta en dos: ¿Es realmente ampliamente adoptada? No, no tan ampliamente como debería ser. ¿Es una buena idea? ¡Sí!
Una enumeración de Java es una clase que solo puede tener un conjunto fijo de N instancias, que están codificadas en la fuente.
Un singleton es una clase que solo puede tener un conjunto fijo de N instancias, que están codificadas en la fuente. Y N == 1.
¡Es tan simple como eso!
El artículo 3 de la Java efectiva de Josh Block (Hacer cumplir la propiedad Singleton con un constructor privado o un enumerador) menciona que "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"
Ejemplo:
public enum Elvis {
INSTANCE;
private final String[] favoriteSongs =
{ "Hound Dog", "Heartbreak Hotel" };
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
}
Continuó: "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 férrea contra la creación de instancias múltiples, incluso en el caso de la serialización sofisticada o los ataques de reflexión".
El mayor negativo que veo es: ¿no se supone que las enumeraciones no tienen un estado mutable? Parece común usar un Singleton con estado.
Entonces, ¿este patrón se ha vuelto más común desde la fecha de publicación (2ª edición publicada en 2008)?
Las enumeraciones pueden tener estado mutable. Generalmente no es una buena idea porque la naturaleza de una enumeración es tener exactamente X versiones de un Tipo Y donde X es más grande que 1, por lo que hacer malabares con el estado (aparte de usar campos / propiedades) se convierte en una pesadilla como cada método debe tener en cuenta todos los estados posibles de todas las constantes de enumeración X.
Pero si va a definir una enumeración con una sola constante de todos modos; simplemente puede tratar esa constante única como un objeto ordinario y hacer todas las suposiciones que lo acompañan. IOW: el problema de tener X versiones de estado desaparece porque X ahora es 1.
No es una buena idea.
Obliga a su clase a heredar de una clase concreta Enum
. Eso contamina tu jerarquía de tipos.
El tipo de la INSTANCE
debe ser exactamente Elvis
; No puede ser algún subtipo de Elvis
.
Más generalmente, no tiene libertad para elegir cómo se instancia la instancia.
Y en términos de sintaxis, ¿es esto realmente demasiado escrito?
public class Elvis {
static public Elvis INSTANCE = new Elvis();
No se supone que ninguna enum
tenga un estado mutable. Las estadísticas no suelen ser mutables. Singletons son solo formas de ofuscar estaticas mutables. (Los objetos sin estado que implementan una interfaz son otro asunto).
Si bien a las enumeraciones generalmente no se les da un estado mutable, este hecho se basa en suposiciones de cómo se utilizará una enumeración. Si bien estas suposiciones generalmente se sostienen, no siempre, y uno de esos casos donde no lo hacen es en la creación de un Singleton.
Si bien no es el uso más común de las enumeraciones, es perfectamente legítimo tener una enumeración con un estado mutable, aunque es posible que desee indicar este hecho en su código para que cualquier otro programador que lo esté viendo no se confunda.
En cuanto a la popularidad de este patrón de diseño, lo he visto con bastante frecuencia, pero no tanto que diría que se ha vuelto "común".