thread safe patterns pattern make java design-patterns singleton

java - safe - Lo que es alternativo a Singleton



make a singleton in java (13)

¿Es posible una clase que contenga solo métodos y campos estáticos? No estoy seguro de cuál es tu situación, pero valdría la pena investigarlo.

Tenemos una clase que contiene información de configuración para la aplicación. Solía ​​ser un singleton. Después de una revisión de arquitectura, nos dijeron que elimináramos el singleton. Vimos algunos beneficios de no usar Singleton en las pruebas unitarias porque podemos probar diferentes configuraciones todas a la vez.

Sin singleton, tenemos que pasar la instancia por todas partes en nuestro código. Se está poniendo muy sucio así que escribimos un contenedor singleton. Ahora estamos portando el mismo código para PHP y .NET, me pregunto si hay un patrón mejor que podamos usar para el objeto de configuración.


Depende de qué herramientas / marcos, etc. están siendo utilizados. Con las herramientas de inyección / ioc de dependencia todavía se pueden obtener optimizaciones / funcionalidades únicas al hacer que el contenedor di / ioc use un comportamiento singleton para la clase requerida (como una interfaz IConfigSettings) creando una única instancia de la clase. Esto podría ser sustituido por las pruebas

Alternativamente, uno podría usar una fábrica para crear la clase y devolver la misma instancia cada vez que la solicite, pero para las pruebas podría devolver una versión tropezada / burlada


El blog de Google Testing tiene una serie de entradas sobre cómo evitar Singleton (para crear código comprobable). Tal vez esto pueda ayudarle:

El último artículo explica en detalle cómo mover la creación de nuevos objetos a una fábrica, para que pueda evitar el uso de singletons. Vale la pena leerlo con seguridad.

En resumen, trasladamos a todos los nuevos operadores a una fábrica. Agrupamos todos los objetos de una vida similar en una sola fábrica.


La alternativa es transmitir lo que necesita en lugar de pedirle cosas a un objeto.


La mejor manera es utilizar un patrón de fábrica en su lugar. Cuando construyes una nueva instancia de tu clase (en la fábrica) puedes insertar los datos ''globales'' en el objeto recién construido, ya sea como referencia a una sola instancia (que almacenas en la clase de fábrica) o copiando los datos relevantes. datos en el nuevo objeto.

Todos sus objetos contendrán los datos que solían vivir en el singleton. No creo que haya mucha diferencia en general, pero puede hacer que su código sea más fácil de leer.


Los singletons no son malos, pero el patrón de diseño es defectuoso. Tengo una clase que solo quiero crear una instancia única de ella durante el tiempo de ejecución, pero quiero crear varias instancias aisladas durante la prueba unitaria para garantizar resultados deterministas.

DI usando Spring, etc., es una muy buena opción pero no la única.


Podría estar diciendo lo obvio aquí, pero ¿hay alguna razón por la cual no puedas usar un marco de inyección de dependencia como Spring o Guice ? (Creo que Spring también está disponible para .NET también ahora).

De esta forma, el marco puede contener una sola copia de los objetos de configuración, y sus beans (servicios, DAO, lo que sea) no tienen que preocuparse por buscarlos.

¡Este es el enfoque que generalmente uso!


Puede lograr el mismo comportamiento de singleton usando métodos estáticos. Steve Yegge lo explica muy bien en this post.


Puede usar un marco de inyección de dependencia para aliviar el dolor de pasar el objeto de configuración. Un decente es un ninject que tiene la ventaja de usar código en lugar de xml.


Quizás tampoco esté muy limpio, pero podría pasar las partes de información que desea cambiar al método que crea el singleton, en lugar de usar

public static Singleton getInstance() { if(singleton != null) createSingleton(); return singleton; } }

puede llamar a createSingleton(Information info) directamente al inicio de la aplicación (y en los métodos de configuración de las pruebas unitarias).


Revisión de la posibilidad de realizar la configuración como interfaz de devolución de llamada. Por lo tanto, su código sensible a la configuración se verá:

MyReuseCode.Configure(IConfiguration)

El código del sistema-init se verá:

Library.init(MyIConfigurationImpl)


no acumule responsabilidades en un solo objeto de configuración, ya que terminará en un objeto muy grande que es difícil de entender y frágil.

Por ejemplo, si necesita otro parámetro para una clase en particular, cambia el objeto de Configuration y luego recompila todas las clases que lo utilizan. Esto es algo problemático.

Intente refactorizar su código para evitar un objeto de Configuration común, global y grande. Pasar solo los parámetros requeridos a las clases del cliente:

class Server { int port; Server(Configuration config) { this.port = config.getServerPort(); } }

debe ser rediseñado para:

class Server { public Server(int port) { this.port = port; } }

un marco de inyección de dependencia ayudará mucho aquí, pero no es estrictamente necesario.


Si usa Spring Framework , puede simplemente crear un bean regular. De forma predeterminada (o si establece explícitamente scope="singleton" ) solo se crea una instancia del bean y esa instancia se devuelve cada vez que se usa el bean en una dependencia o se recupera a través de getBean() .

Usted obtiene la ventaja de la instancia única, sin el acoplamiento del patrón de Singleton.