java - patrones - Patrón de diseño Singleton: escollos
patrones de diseño java ejemplos (4)
Además de los problemas de prueba y diseño mencionados en otras publicaciones, existen problemas con Singletons y classloaders. Los singletons no son realmente "únicos" por JVM o aplicación; lo logran a través de la propiedad estática, lo que realmente significa que hay uno por clase. Si hay varios cargadores de clases, como en la mayoría de los servidores de aplicaciones, cada aplicación por separado obtiene un nuevo cargador de clases, incluso se utilizan varios niveles de cargadores de clases en EJB. Se carga una instancia de singleton por cargador de clases, lo que, dependiendo de lo que esté haciendo con el singleton, puede no producir los resultados que espera.
Actualmente estoy muy interesado en este "patrón de diseño". Aunque no estoy seguro si hay caídas usando esta estricta implementación de estado global. Entonces, ¿cuándo piensas no practicar singleton en una aplicación?
Google Tech Talks tuvo hace algún tiempo una buena presentación sobre Global State y Singletons . El patrón de singleton estático es malo, porque causa efectos secundarios no deseados y hace que el código no sea comprobable. Static singleton es la versión OO de las variables globales.
La solución es simplemente crear una instancia del objeto y pasarla a sus usuarios a través de la inyección de dependencia. Los marcos de DI, como Guice , facilitan la definición del buen tipo de singleton (en Guice simplemente anota una clase con @Singleton). Hubo un Tech Talk similar llamado ¡No busques cosas! que discutió DI más.
Por lo general, Singleton es una mala idea si está realizando pruebas unitarias, y generalmente es una mala idea no hacer pruebas unitarias (o BDD o pruebas de aceptación).
Hacer que los objetos tengan un estado global significa que las pruebas de la unidad que escribes que involucran a estos objetos se aislarán y separarán entre sí. En cambio, tendrá que preocuparse por restablecer el estado de cada prueba y créame ... eso nunca se hace el 100% del tiempo. Si no restablece el estado global, entonces comienza a obtener errores muy extraños y difíciles de depurar en sus pruebas, lo que hace perder tiempo.
El estado global también aumenta el acoplamiento en su código y hace que sea muy difícil refactorizar.
El método ideal sería usar un contenedor IoC / DI (Spring, Guice, etc.) para solicitar objetos. Estos contenedores a menudo tienen formas de hacer que los objetos aparezcan como ''Singletons'', pero también tienen formas de modificar ese comportamiento según la situación (es decir, pruebas unitarias frente a su código de dominio).
Todo esto depende del tamaño de tu problema, por supuesto. Si está pirateando un equipo de prueba de 4 clases para probar algo, entonces use un Singleton. Sin embargo, tan pronto como ese proyecto cobre vida y se vuelva más grande y más complejo, refactorizar el Singleton.
Usaría un Singleton muy raramente. Debido a su naturaleza (objetos estáticos, globales) son difíciles de usar en la prueba de unidad de su código. Termina necesitando sincronizar o crear algunos mecanismos de reinicialización para que pueda obtener una versión nueva para cada prueba unitaria. Hay casos que tienen sentido, por ejemplo, una clase de configuración global, pero son mucho menos de lo que parecen creer las personas nuevas en singleton. Sé que pasé por una fase en la que vi aplicaciones del patrón singleton en todas partes. Ahora lo evito donde puedo y lo deshago a través de la refactorización en mi código, ya que me encuentro con una implementación innecesaria.