2010-08-20 22 views
32

¿Cómo se diferencia un singleton de una clase con solo campos estáticos?¿Cuál es la diferencia entre un patrón de Singleton y una clase estática en Java?

+1

¿Estás preguntando "¿cuáles son las diferencias prácticas?" –

+0

tengo curiosidad acerca de las diferencias generales de los dos, es decir, ¿hay algo único en un Singleton que lo diferencie de una clase que tiene todos sus métodos y atributos establecidos en estática? – cesar

+0

La forma de DCL de implementar singleton tiene solo una instancia de campo estático que contiene una referencia estática al objeto singleton y luego instancia de forma perezosa en un método estático. En este caso, esta implementación de Singleton solo tiene campos y métodos estáticos y son iguales (no son diferentes a las preguntas). Esa es una implementación. Otro puede ser a través de Enum. – nanosoft

Respuesta

32

Casi cada vez que escribo una clase estática, termino deseando haberlo implementado como una clase no estática. Considere:

  • Se puede extender una clase no estática. El polimorfismo puede ahorrar mucha repetición.
  • Una clase no estática puede implementar una interfaz, que puede ser útil cuando desee separar la implementación de la API.

Debido a estos dos puntos, las clases no estáticas permiten escribir pruebas de unidades más confiables para los elementos que dependen de ellas, entre otras cosas.

Sin embargo, un patrón singleton está solo a medio paso de las clases estáticas. Usted tipo de obtiene estos beneficios, pero si accede a ellos directamente dentro de otras clases a través de `ClassName.Instance ', está creando un obstáculo para acceder a estos beneficios. Al igual que ph0enix señaló, es mucho mejor utilizar un patrón de inyección de dependencia. De esta forma, se puede decir a un marco DI que una clase en particular es (o no es) un singleton. Obtienes todos los beneficios de la burla, las pruebas unitarias, el polimorfismo y mucha más flexibilidad.

+0

En java, la clase estática anidada puede extender otras clases (y también puede ser extendida por otras clases) e implementar interfaces. check http://stackoverflow.com/a/37114702/1406510 – nanosoft

+3

@nanosoft: Cuando dije "una clase estática", no me refería a Java ["clases estáticas estáticas"] (http://docs.oracle. com/javase/tutorial/java/javaOO/nested.html), sino más bien una "clase llena solo de campos estáticos", como preguntaba el OP. Todas las declaraciones que hago aquí se aplican si piensas en términos de usar métodos estáticos, independientemente de la naturaleza de la clase en la que se encuentren: no pueden implementar interfaces o extenderse.Lo siento por cualquier confusión que pueda haber causado al decir "clase estática", ese es un término que es más común en otros idiomas, pero no se aplica en Java. – StriplingWarrior

2

Al menos puede reemplazarlo más fácilmente por un simulacro o un talón para probar la unidad. Pero no soy un gran admirador de los singleton por exactamente la razón que estás describiendo: son variables globales disfrazadas.

+0

En realidad, creo que tener un singleton te ayuda a reducir el número de variables globales. Usted tiene una referencia a un objeto. Podría envolver todos los campos estáticos en él. – BenoitParis

+4

@BenoitParis: reduce el número absoluto de variables globales pero no resuelve ninguno de los males asociados con ellas. –

+2

No debe tener variables globales en primer lugar. Incluso tener métodos estáticos no es realmente POO. –

5

Un singleton se puede inicializar perezosamente, por ejemplo.

+2

La estática es de todos modos. –

+0

@Tom Hawtin - tachado: ¿qué quieres decir con eso? – JRL

+6

Los campos de Estática no son realmente flojos. Los campos estáticos se cargan cuando un cargador de clases carga la clase. Se puede escribir un singleton de manera que la instancia de singleton no se inicialice en la carga de clases, sino en la primera solicitud de la instancia de singleton. Por supuesto, el enfoque más común para los singletons no es perezoso. –

2

Un singleton es una clase con solo una instancia, forzada. Esa clase puede tener estado (sí sé que las variables estáticas mantienen el estado), no todas las variables o métodos miembros deben ser estáticos.

Una variación sería un pequeño grupo de estos objetos, lo que sería imposible si todos los métodos fueran estáticos.

+0

Pregunta pregunta sobre campos, no métodos. –

+0

¿Un pequeño grupo de objetos únicos? Supongo que tiene sentido, por algún valor de "pequeño". –

3

La diferencia es independiente del idioma. Singleton es por definición: "Asegúrese de que una clase tenga solo una instancia y proporcione un punto de acceso global a ella." Una clase llena de solo campos estáticos no es igual a singleton, pero tal vez en su escenario de uso brinden la misma funcionalidad. Pero como JRL dijo que la iniciación perezosa es una diferencia.

2

Una clase singleton tendrá una instancia que generalmente es una y solo una por cargador de clases. Por lo tanto, puede tener métodos regulares (no estáticos) y se pueden invocar en esa instancia particular.

Aunque es una clase con solo métodos estáticos, realmente no hay necesidad de crear una instancia (por esta razón, la mayoría de las personas/frameworks hacen que este tipo de clases de Util sean abstractas). Simplemente invocará los métodos en clase directamente.

1

Lo primero que se le viene a la mente es que si desea utilizar una clase con solo métodos y atributos estáticos en lugar de un singleton, tendrá que usar el inicializador estático para inicializar correctamente ciertos atributos. Ejemplo:

class NoSingleton { 
    static { 
    //initialize foo with something complex that can't be done otherwise 
    } 
    static private foo; 
} 

Esto se ejecutará en el tiempo de carga de la clase que probablemente no sea la que desea. Usted tiene más control sobre este shebang completo si lo implementa como singleton. Sin embargo, creo que usar singletons no es una buena idea en ningún caso.

+0

Creo que para usted decir que los singletons "no son una buena idea", cuando no sabemos nada sobre el contexto en el que podría estar usándolos, es un poco precipitado. No hay nada absoluto en la programación, y casi siempre hay un caso de uso que hace que uno u otro sea el mejor. Es como decirle a alguien que la palabra "pato" siempre se refiere a un animal. Pero el contexto es importante, ya que podría significar algo completamente diferente como "Pato cuando alguien te arroje un espectáculo". PD Pero no te devolví el voto. – AaronLS

0

NOTA: Los ejemplos están en C#, ya que eso es con lo que estoy más familiarizado, pero el concepto debería aplicarse a Java de la misma manera.

Ignorando el debate sobre cuándo es apropiado usar objetos Singleton, una diferencia principal que conozco es que un objeto Singleton tiene una instancia que puede pasar.

Si usa una clase estática, se conecta estrictamente a una implementación particular, y no hay forma de alterar su comportamiento en tiempo de ejecución.

Mal diseño usando clase estática:

public class MyClass 
{ 
    public void SomeMethod(string filename) 
    { 
     if (File.Exists(filename)) 
     // do something 
    } 
} 

Alternativamente, usted podría tener su constructor toma en una instancia de una interfaz en particular en su lugar. En producción, podría usar una implementación de Singleton de esa interfaz, pero en las pruebas unitarias, simplemente puede burlarse de la interfaz y alterar su comportamiento para satisfacer sus necesidades (haciendo que arroje alguna excepción oscura, por ejemplo).

public class MyClass 
{ 
    private IFileSystem m_fileSystem; 

    public MyClass(IFileSystem fileSystem) 
    { 
     m_fileSystem = fileSystem; 
    } 

    public void SomeMethod(string filename) 
    { 
     if (m_fileSystem.FileExists(filename)) 
     // do something 
    } 
} 

Esto no quiere decir que las clases estáticas son siempre malas, pero no es un gran candidato para cosas como sistemas de archivos, bases de datos, conexiones y otras dependencias de la capa inferior.

0

Una de las principales ventajas de los singleton es que puede implementar interfaces y heredar de otras clases. A veces tiene un grupo de singletons que proporcionan una funcionalidad similar en la que desea implementar una interfaz común, pero son responsables de un recurso diferente.

+0

La clase estática anidada también puede extender otra clase e implementar la interfaz. http://stackoverflow.com/a/37114702/1406510 – nanosoft

0

Singleton Class: Singleton Class es una clase de la cual solo existe una sola instancia por cargador de clases.

Helper Class (Clase con solo campos/métodos estáticos): No existe ninguna instancia de esta clase. Solo se puede acceder directamente a los campos y métodos como constantes o métodos auxiliares.

Estas pocas líneas de este blog lo describe muy bien:

En primer lugar el patrón Singleton es muy útil si desea crear una instancia de una clase. Para mi clase de asistente , realmente no queremos instanciar cualquier copia de la clase. La razón por la cual no se debe utilizar una clase Singleton se debe a que para esta clase ayudante no utilizamos ningún variables. La clase Singleton sería ser útil si contenía un conjunto de variables que que queríamos sólo un conjunto de y los métodos utilizados esos variables, pero en nuestra clase de ayuda que no utiliza ninguna variable aparte de las aprobadas en los (que hacemos final). Por esta razón no creo que queremos una instancia singleton porque no queremos ninguna variable y no queremos que nadie instantianting esta clase. Así que si no quieres que nadie crear instancias de la clase, que es normalmente si usted tiene algún tipo de ayudante/clase utils entonces utilizar el lo que llamo la clase estática, una clase con un constructor privada y sólo consiste en métodos estáticos sin ningún ninguna variable.

11

Vamos a resumir :)

La diferencia esencial es: La forma de existencia de un singleton es un objeto, no es estática. Esto condujo a las siguientes cosas:

  • Singleton se puede ampliar. Estático no.
  • La creación de Singleton puede no ser segura en caso de subprocesamiento si no se implementa correctamente. Estático no.
  • Singleton se puede pasar como un objeto. Estático no.
  • Singleton puede ser basura recolectada. Estático no.
  • ¡Singleton es mejor que la clase estática!
  • Más aquí, pero no me he dado cuenta todavía :)

Por último, pero no menos importante, cada vez que se va a poner en práctica un conjunto unitario, por favor considere que rediseñar su idea de no usar este objeto a Dios (créanme, tenderás a poner todas las cosas "interesantes" en esta clase) y usarás una clase normal llamada "Contexto" o algo así.

+0

+1 para el principio "Objeto de Dios". Quiéralo. – StriplingWarrior

+0

En java, la clase estática anidada puede extenderse a otra clase (y también puede extenderse por otras clases). la clase anidada estática se puede pasar mucho como objeto. Puede ser basura recogida también. compruebe http://stackoverflow.com/a/37114702/1406510 – nanosoft

+0

Las clases estáticas pueden ser seguras para subprocesos o no seguras para subprocesos. – user2864740

3

Creo que lo importante es 'objeto' en la programación orientada a objetos. Excepto en algunos casos, deberíamos restringirnos al uso de clases estáticas. Los casos son:

  1. Cuando crear un objeto no tiene sentido. Me gusta los métodos de java.lang.Math. Podemos usar la clase como un objeto. Porque el comportamiento de Math métodos de clase no depende del estado de los objetos que se crearán en esta clase.
  2. Códigos que deben utilizarse conjuntamente por más de un método de objeto, los códigos que no llegan a las variables del objeto y es probable que se cierre fuera puede ser métodos estáticos

Otra cosa importante es Singleton es extensible. Singleton se puede extender. En la clase Math, utilizando los métodos finales, se ha evitado la creación y extensión del objeto de esta clase. Lo mismo es cierto para la clase java.lang.System. Sin embargo, la clase Runtime es un único objeto, no un método estático. En este caso, puede anular los métodos de herencia de la clase Runtime para diferentes propósitos.

Puede retrasar la creación de un objeto Singleton hasta que sea necesario (carga lenta). Sin embargo, para las clases de métodos estáticos, no existe una condición. Si llega a cualquier miembro estático de la clase, la clase se cargará en la memoria.

Como resultado, el beneficio más básico para la clase de método estático es que no tiene que crear un objeto, pero cuando se utiliza incorrectamente, eliminará su código de orientado a objetos.

+0

# 1 debe tomarse en contexto. Tome una llamada '' Date.Now' sin sentido. sin embargo, el 99,99% de las veces con la llamada a método estático 'Date.Now' hace que las pruebas de burla sean casi imposibles. O más bien, los métodos estáticos * no * generalmente permiten inyección y burla. – user2864740

Cuestiones relacionadas