¿Por qué la implementación de un patrón de Singleton en el código de Java es (a veces) considerado un antipatrón en el mundo de Java?

He visto a algunas personas en SO al comentar que Singleton Pattern es un antipatrón. Quiero saber por qué ?

Pruebas

Una razón es que los singletons no son fáciles de manejar con pruebas unitarias. No puede controlar la creación de instancias y, por su propia naturaleza, puede retener el estado en todas las invocaciones.

Por esa razón, el principio de la dependency injection es popular. Cada clase se inyecta (configura) con las clases que necesitan para funcionar (en lugar de derivar a través de accesadores singleton) y así las pruebas pueden controlar qué instancias de clase dependientes usar (y proporcionar simulaciones si es necesario).

Los marcos como Spring controlarán el ciclo de vida de sus objetos y a menudo crearán singletons, pero estos objetos se inyectan en sus objetos dependientes por el marco. Por lo tanto, la base de código en sí misma no trata los objetos como singletons.

por ejemplo, en lugar de esto (por ejemplo)

public class Portfolio { private Calculator calc = Calculator.getCalculator(); } 

usted inyectaría la calculadora:

 public class Portfolio { public Portfolio(Calculator c) { this.calc = c; } } 

Por lo tanto, el objeto Portfolio no sabe / no importa cuántas instancias de la Calculator existan. Las pruebas pueden inyectar una Calculator ficticia que facilita las pruebas.

Concurrencia

Al limitarse a una instancia de un objeto, las opciones para enhebrar son limitadas. El acceso al objeto singleton puede tener que ser protegido (por ejemplo, a través de la sincronización). Si puede mantener varias instancias de esos objetos, puede adaptar el número de instancias a los hilos que tiene en ejecución y boost las capacidades simultáneas de su base de código.

Mi opinión personal es que viola el principio de responsabilidad única. Los objetos Singleton son responsables tanto de su propósito como de controlar el número de instancias que producen, lo cual creo que es incorrecto.

Esta es la razón por la cual muchas personas delegan el control en un objeto de fábrica.

[Mutable] Singleton es un anti-patrón de un anti-patrón.

El antipatrón subyacente significativo es el estado global (o estado ambiental). Con estado global, tiene un gran blog de dependencia en su progtwig. Esto afecta las pruebas, pero eso es solo una parte de las consecuencias de la mala progtwigción.

En capas, Singleton agrega un nivel de complejidad completamente innecesario frente a la simple statement de campos static mutables.

Los singletons como tales no son necesariamente un antipatrón, pero tienen pocos beneficios y se vuelven antipatrón cuando se usan incorrectamente (lo que sucede a menudo).

A menudo, los singletons no son singletons en absoluto, sino “variables globales disfrazadas”. Además, a menudo se usan cuando la propiedad “única instancia” no es realmente una ventaja. (que de nuevo se equilibra por el hecho de que muchas veces la implementación es incorrecta al mismo tiempo).

Además de eso, pueden ser difíciles de implementar teniendo en cuenta multihilo (a menudo se hace incorrectamente o de manera ineficiente), y pierden la mayoría de sus beneficios si quieres controlar su creación de instancias.

Si desea tener control sobre la creación de instancias, debe hacerlo a mano en algún momento al inicio del progtwig, pero también podría simplemente crear una instancia de un objeto normal y pasarlo a otro.
Si el orden de destrucción es de alguna preocupación, debe implementarlo manualmente también. Un único objeto automático en la función principal es mucho más limpio y fácil.

Hay muchos requisitos que puede tener en el singleton:

  1. inicialización lenta;
  2. eliminación adecuada;
  3. scope (uno por hilo, por ejemplo).

Normalmente, también tendrá muchos solteros en su aplicación, y el patrón Singleton no permite el código reutilizable. Por lo tanto, si desea implementar todas estas inquietudes para todos sus singletons, verá inmediatamente su calidad antipatrón .

Extraño. Parece que la implementación incorrecta de un Singleton es un “antipatrón”, no el Singleton en sí mismo.

Creo que hemos olvidado que cada progtwig tiene que comenzar en alguna parte. Tiene que haber una implementación concreta de cada abstracción, y finalmente cada dependencia se resolverá eventualmente, o su aplicación no sería de mucha utilidad.

La mayoría de los marcos DI permiten instanciar una clase como Singleton, simplemente lo maneja por usted. Si elige hacer DI usted mismo, inyectar un singleton no es un problema. También se puede probar un Singleton IS, y si está usando DI para inyectarlo, no hace que una clase sea inestable.

IMO, como cualquier otro patrón (incluyendo DI e IoC) es una herramienta. A veces se ajusta, otras veces no.