제이온

[Effective Java] Item 3. Garantizar el singleton con un constructor privado o un tipo enum

Creado: 2024-04-27

Creado: 2024-04-27 00:48

Singleton

Concepto de Singleton

Singleton se refiere a una clase que solo puede crear una instancia. Los ejemplos típicos de Singleton incluyen objetos sin estado o componentes únicos del sistema. Sin embargo, las clases Singleton presentan el problema de ser difíciles de probar a menos que el tipo se defina como una interfaz y su implementación se defina por separado.


Cómo crear un Singleton

Método de miembro público estático que es un campo final



El constructor privado solo se llama una vez al inicializar la instancia de Elvis, asegurando que sea la única en todo el sistema. Sin embargo, es posible usar AccessibleObject.setAccessible() para llamar al constructor privado, y este método de modificación mediante reflexión se puede bloquear lanzando una excepción cuando se crea el segundo objeto.


  • Ventajas
    • Está claro en la API que la clase es un Singleton.
    • Es conciso.


Método de fábrica estático público que proporciona


Aparte de la modificación a través de la reflexión, este método también garantiza que sea la única instancia en todo el sistema. Simplemente cambia el campo a privado y usa el método de fábrica estático para devolver el objeto.


  • Ventajas
    • Se puede cambiar a no Singleton sin cambiar la API.
      • Por ejemplo, el método de fábrica estático puede devolver una instancia diferente para cada hilo.
    • Se puede cambiar a un método de fábrica Singleton genérico si se desea.
    • La referencia al método de la fábrica estática se puede usar como proveedor.
      • Por ejemplo, se puede usar Supplier<Elvis> en lugar de Elvis::getInstance.


Si no necesita usar las ventajas anteriores, es mejor usar el primer método.


Usando el tipo de enumeración


La mejor manera es usar el tipo de enumeración. Es más seguro contra ataques de reflexión y el código es más limpio que los dos métodos anteriores. Además, como se explicará más adelante, los dos métodos anteriores tienen la desventaja de que se debe agregar código adicional al serializar.

Sin embargo, debe tener en cuenta que, si bien el Singleton que desea crear puede heredar una interfaz, no puede heredar una clase.


Puntos a tener en cuenta al serializar una clase Singleton

Si desea serializar una clase Singleton creada con el primer o segundo método anterior, debe declarar todos los campos de instancia como transitorios y redefinir el método readResolve() además de simplemente implementar Serializable.



Fuentes

Comentarios0