¿Por qué usar un singleton en lugar de métodos estáticos?

93

Nunca encontré buenas respuestas a estas simples preguntas sobre las clases de ayuda / utilidad:

¿Por qué debería crear un singleton (sin estado) en lugar de usar métodos estáticos?

¿Por qué se necesitaría una instancia de objeto si un objeto no tiene estado?

Sebastien Lorber
fuente
posible duplicado de stackoverflow.com/questions/720744/static-class-and-singleton
Michael Borgwardt
No piense, ya que hablamos de 2 idiomas diferentes, por lo que la respuesta puede variar, pero gracias por el enlace, en Java nunca escuché el término "monoestado"
Sebastien Lorber

Respuestas:

79

A menudo, los singleton se utilizan para introducir algún tipo de estado global en una aplicación. (Más a menudo de lo realmente necesario, para ser honesto, pero ese es un tema para otro momento).

Sin embargo, hay algunos casos de esquina en los que incluso un singleton sin estado puede ser útil:

  • Espera ampliarlo con el estado en el futuro previsible.
  • Necesita una instancia de objeto por alguna razón técnica en particular .
    Ejemplo: objetos de sincronización para C # locko Javasynchronized declaración de .
  • Necesita herencia, es decir, quiere poder reemplazar fácilmente su singleton con otro usando la misma interfaz pero una implementación diferente.
    Ejemplo: el Toolkit.getDefaultToolkit()método en Java devolverá un singleton cuyo tipo exacto depende del sistema.
  • Quieres igualdad de referencia para un valor centinela .
    Ejemplo: DBNull.Valueen C #.
Heinzi
fuente
27
Voy a ir con +1, aunque en mi humilde opinión, los singletons se utilizan incorrectamente para introducir estados globales. El propósito de un singleton no es hacer que un objeto esté disponible globalmente, sino hacer cumplir que un objeto se instancia solo una vez. Los objetos globales son un mal necesario. A menos que sea realmente necesario, uno debe intentar no usarlos, ya que generalmente conducen a un alto acoplamiento, con SomeSingleton.getInstance (). SomeMethod () por todas partes. :)
back2dos
Puede ser útil en juegos en los que solo desea una instancia de procesamiento en lugar de varias instancias de procesamiento, o con una clase de canalización de red en la que configura un canal seguro en el que solo puede haber una conexión a la vez.
Tschallacka
2
"Reemplazar fácilmente su singleton" es el punto más importante desde mi punto de vista. El descanso está bastante cerca de la implementación de la clase estática.
Teoman shipahi
1
Los singleton son valores centinela no nulos útiles para tipos de suma / producto y similares. Por ejemplo, siendo el valor Ninguno / Nada en un tipo de Opción o el valor Vacío para un tipo de colección. Obtiene una prueba rápida de Ninguno / Vacío como beneficio adicional, porque la igualdad de referencia es todo lo que se necesita.
itsbruce
@itsbruce: sus ejemplos no son singleton : la lista vacía no es la única instancia posible de la clase List, y el valor None no es la única instancia posible de la clase Option. Sin embargo, hay ejemplos en los que el valor centinela son singleton, y me he tomado la libertad de agregar uno a mi respuesta. ¡Gracias por la entrada!
Heinzi
37

Pude ver un caso de uso de un singleton sin estado en lugar de una clase de métodos estáticos, es decir, para la inyección de dependencia .

Si tiene una clase auxiliar de funciones de utilidad que está usando directamente, crea una dependencia oculta; no tienes control sobre quién puede usarlo o dónde. Inyectar esa misma clase auxiliar a través de una instancia singleton sin estado le permite controlar dónde y cómo se usa, y reemplazarlo / simularlo / etc.cuando lo necesite.

Convertirlo en una instancia de singleton simplemente asegura que no está asignando más objetos del tipo de los necesarios (ya que solo necesita uno).

tzaman
fuente
1
"no tienes control sobre quién puede usarlo o dónde". ¿Por qué alguien lo necesitaría?
hagrawal
1
@hagrawal para fines de prueba, debería poder burlarse de él
Jemshit Iskenderov
15

En realidad, encontré otra respuesta que no se menciona aquí: los métodos estáticos son más difíciles de probar.

Parece que la mayoría de los marcos de prueba funcionan muy bien para simular métodos de instancia, pero muchos de ellos no manejan de manera decente la simulación de métodos estáticos.

Sebastien Lorber
fuente
2
Pero Powermock parece poder hacerlo
Sebastien Lorber
6

En la mayoría de los lenguajes de programación, las clases eluden mucho el sistema de tipos. Si bien una clase, con sus métodos y variables estáticos, es un objeto, muy a menudo no puede implementar una interfaz o extender otras clases. Por eso, no se puede utilizar de manera polimórfica, ya que no puede ser el subtipo de otro tipo. Por ejemplo, si tiene una interfaz IFooable, que es requerida por varias firmas de métodos de otras clases, el objeto de clase StaticFoono puede usarse en lugar de IFooable, mientras que FooSingleton.getInstance()puede (asumiendo, FooSingletonimplementa IFooable).

Tenga en cuenta que, como comenté en la respuesta de Heinzi, un singleton es un patrón para controlar la instanciación. Reemplaza new Class()con Class.getInstance(), lo que le da al autor deClass más control sobre las instancias, que puede usar para evitar la creación de instancias innecesarias. El singleton es solo un caso muy especial del patrón de fábrica y debe tratarse como tal. El uso común lo convierte más bien en el caso especial de los registros globales, que a menudo terminan mal, porque los registros globales no deben usarse simplemente a voluntad.

Si planea proporcionar funciones auxiliares globales, los métodos estáticos funcionarán bien. La clase no actuará como clase, sino simplemente como un espacio de nombres. Sugiero que conserve una alta cohesión o podría terminar con problemas de acoplamiento más extraños.

greetz
back2dos

back2dos
fuente
4

Existe una compensación entre el uso de cuál. Los singleton pueden tener o no estado y se refieren a objetos. Si no mantienen el estado y solo se usan para acceso global, entonces la estática es mejor ya que estos métodos serán más rápidos. Pero si desea utilizar objetos y conceptos de programación orientada a objetos (polimorfismo de herencia), el singleton es mejor.

Considere un ejemplo: java.lang.Runtime es una clase singleton en java. Esta clase permite diferentes implementaciones para cada JVM. La implementación es única por JVM. Si esta clase hubiera sido estática, no podemos pasar diferentes implementaciones basadas en JVM.

Encontré este enlace realmente útil: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

¡¡Espero eso ayude!!

Atihska
fuente
Esta respuesta es buena para incluir un ejemplo concreto en el mundo real.
systemovich
2

Para mí, "el estado del objeto de deseo usa Singleton, la función de deseo usa el método estático"

Depende de lo que quieras. Siempre que desee el estado del objeto (por ejemplo, polimorfismo como estado nulo en lugar de null, o estado predeterminado), singleton es la opción adecuada para usted, mientras que el método estático se usa cuando necesita una función (recibir entradas y luego devolver una salida).

Recomiendo para el caso de singleton, debe ser siempre el mismo estado después de que se instancia. No debe ser clonable ni recibir ningún valor para establecer (excepto la configuración estática del archivo, por ejemplo , el archivo de propiedades en Java).

PD: El rendimiento entre estos 2 es diferente en milisegundos, así que concéntrate en la arquitectura primero.

Toomtarm Kung
fuente
1

Singleton no es apátrida, tiene el estado global.

Algunas razones por las que puedo pensar en usar Singleton son:

  • Para evitar pérdidas de memoria
  • Para proporcionar el mismo estado para todos los módulos en una aplicación, por ejemplo, conexión de base de datos.
Indigo Praveen
fuente
Lo sé, pero en realidad un singleton puede ser más o menos apátrida ... Si no comparte ningún atributo de clase ...
Sebastien Lorber