2010-06-23 9 views
20

El artículo 3 de de Josh Block Effective Java (Aplicar la propiedad Singleton con un constructor privado o un enumerador) menciona que "aunque este enfoque aún no se ha adoptado ampliamente, un tipo de enumeración de elemento único es la mejor manera de implementar un semifallo."¿Es el Single-Element Enum Type Singleton realmente una buena idea ampliamente adoptada?

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 a la aproximación del campo público, excepto que es más conciso, proporciona el mecanismo de serialización de forma gratuita, y proporciona una garantía rigurosa contra la creación de instancias múltiples, incluso frente a sofisticados ataques de serialización o reflexión ".

El mayor aspecto negativo que veo es: ¿no se supone que las enumeraciones tienen estado mutable? Parece común usar un Singleton con estado.

Entonces, ¿este patrón en realidad se ha vuelto más común desde la fecha de publicación (segunda edición publicada en 2008)?

+0

¿Soy la única persona que se siente incómoda por cómo las enumeraciones en Java pueden comportarse como clases? Parece que Java decidió eliminar los "tipos de aspecto natural" que podría hacer en C++ al sobrecargar los métodos, y convirtió las enumeraciones directas en esta extraña burbuja. – Uri

+1

C++ se acerca a las enumeraciones como una extensión del uso de ints para el cambio, por lo que son construcciones muy simples. En Java, por otro lado, las enumeraciones se conciben como clases legítimas, con toda la funcionalidad que trae consigo, que difieren solo en su restricción (principal) en la creación de instancias. Tienen el mismo nombre porque sus usos se superponen en algunas áreas importantes, pero tengan cuidado de compararlos demasiado de cerca: son bestias muy diferentes. – tlayton

+1

@Uri, 'enum's en Java no se comportan simplemente como clases, son _ clases_. Todos extienden implícitamente 'java.lang.Enum'. – Pops

Respuesta

10

Si bien las enumeraciones generalmente no tienen un estado mutable, este hecho se basa en supuestos de cómo se usará una enumeración. Si bien estas suposiciones generalmente se cumplen, 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 enums, 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é buscando no lo haga confundirse.

En cuanto a la popularidad de este patrón de diseño, lo he visto con bastante frecuencia, pero no tanto como para decir que se ha vuelto "común".

3

Las enumeraciones pueden tener estado mutable. Por lo general, no es una buena idea porque la naturaleza de una enumeración es tener exactamente X versiones de un Tipo Y donde X es mayor que 1, por lo que hacer malabares con el estado (aparte de usar campos/propiedades) se convierte en una pesadilla ya que cada método necesita tener en cuenta todo el estado posible de todas las constantes de X enum.

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 la acompañan. IOW: el problema de tener X versiones de estado desaparece porque X ahora es 1.

8

(Esta respuesta presume que un producto único "forzada" es realmente lo que quiere, en contraposición a una de facto Singleton gestionado por el marco DI (por ejemplo @Singleton de Guice), que es probablemente más a menudo la idea correcta.)

Para descomponer su pregunta en dos: ¿Es realmente ampliamente adoptado? No, no tan ampliamente como debería ser. ¿Es una buena idea? ¡Sí!

Una enumeración 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 así de simple!

1

No se supone que los enum s tengan estado mutable. La estática no debería ser generalmente mutable. Los singletons son solo formas de ofuscar la estática mutable.(Los objetos sin estado que implementan una interfaz son otra cuestión).

-3

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 INSTANCE debe ser exactamente Elvis; no puede ser un subtipo de Elvis.

En general, no tiene libertad para elegir cómo se instancia la instancia.

Y en cuanto a la sintaxis, ¿es realmente demasiado tipeo?

public class Elvis { 
    static public Elvis INSTANCE = new Elvis(); 
+4

Si crees que es remotamente equivalente a lo que escribiste aquí, te recomiendo leer el artículo de EJ. Y nadie te está obligando a exponer a Elvis como un Elvis. Puede exponerlo (a través de un método) como cualquier supertipo que desee, y esta es una buena práctica general de todos modos ya que le deja la flexibilidad de usar la inicialización perezosa cuando lo desee. Eso despacha una de sus preocupaciones, ¿y qué significa "contamina su jerarquía de tipos"? –

Cuestiones relacionadas