2008-09-05 9 views
82

Indique las consideraciones de diseño al decidir entre el uso de un singleton frente a una clase estática. Al hacer esto, te ves forzado a contrastar los dos, así que cualquier contraste que puedas encontrar también es útil para mostrar tu proceso de pensamiento. Además, a todos los entrevistadores les gusta ver ejemplos ilustrativos. :)¿Cuándo debería usar el patrón singleton en lugar de una clase estática?

+0

una clase java no puede hacer estática a menos que sea una clase interna – Harshana

+1

Si el estado del objeto sí importa, entonces use singleton; de lo contrario, use una clase estática. –

Respuesta

79
  • Los Singleton pueden implementar interfaces y heredar de otras clases.
  • Los Singletons se pueden cargar de forma diferida. Solo cuando realmente se necesita. Eso es muy útil si la inicialización incluye una costosa carga de recursos o conexiones de bases de datos.
  • Singletons ofrecen un objeto real.
  • Los Singleton se pueden extender a una fábrica. La gestión de objetos detrás de escena es abstracta, por lo que es mejor mantenerla y da como resultado un mejor código.
+2

Eche un vistazo a este enlace también: http://codeofdoom.com/wordpress/2008/04/20/how-and-when-to-use-singleton-classes/ – Amit

+4

"Los Singleton pueden ser una carga lenta ed "- en C#, el constructor estático solo se invoca la primera vez que se hace referencia a un miembro estático. En PHP, puede usar la carga automática para que solo se ejecute la primera vez que se usa la clase. – mpen

+0

Las inicializaciones estáticas de Java también son flojas. No hay puntos para Singleton allí. – MikeFHay

-1

Cuando la clase individual necesita estado. Singletons mantienen un estado global, las clases estáticas no.

Por ejemplo, haciendo un ayudante en torno a una clase de registro: Si tiene colmena cambiable (hKey usuario actual vs. HKEY Local Machine) que podría ir:

RegistryEditor editor = RegistryEditor.GetInstance(); 
editor.Hive = LocalMachine 

ahora más llamadas a ese Singleton operará en la colmena de la máquina local. De lo contrario, utilizando una clase estática, deberá especificar que la máquina local colgará everytiem, o tener un método como ReadSubkeyFromLocalMachine.

+1

Discutiría en contra de usar un Singleton de esta manera ... Es muy peligroso mantener los estados persistentes, porque la próxima persona que llama puede olvidarse de configurar la colmena, y escribir en el registro en la colmena equivocada ... :-(es probablemente un ejemplo de uso indebido que hace que la gente piense que los Singletons son malos. – nus

8

Yo diría que la única diferencia es la sintaxis: MySingleton.Current.Whatever() vs MySingleton.Whatever(). El estado, como David mencionó, es en última instancia "estático" en cualquier caso.


EDIT: La brigada enterrar vino de digg ... de todos modos, pensé en un caso que requeriría un conjunto unitario. Las clases estáticas no pueden heredar de una clase base ni implementar una interfaz (al menos en .Net no pueden). Entonces, si necesita esta funcionalidad, debe usar un singleton.

2

Si por "clase estática" te refieres a una clase que solo tiene variables estáticas, entonces en realidad pueden mantener el estado. Mi entendimiento es que la única diferencia sería cómo acceder a esto. Por ejemplo:

MySingleton().getInstance().doSomething(); 

frente

MySingleton.doSomething(); 

Los detalles internos de MySingleton, obviamente, será diferente entre ellos, pero, cuestiones de hilo de seguridad a un lado, ambos realizarán la misma en relación con el código de cliente.

+2

Los singletons son en sí mismos objetos -> se pueden pasar como argumentos. –

1

Nunca deben usarse Singletons (a menos que considere que una clase sin estado mutable es singleton). "clases estáticas" no deberían tener ningún estado mutable, salvo quizás cachés seguros para subprocesos y similares.

Casi cualquier ejemplo de singleton muestra cómo no hacerlo.

+3

¿Qué pasa con las clases de administrador que controlan los recursos de hardware? ¿Qué hay de las clases de archivo de registro? – RJFalconer

0

Si un singleton es algo que puede desechar, para limpiarlo después, puede considerarlo cuando es un recurso limitado (es decir, solo 1) que no necesita todo el tiempo, y tiene algunos tipo de memoria o costo de recursos cuando se asigna.

El código de limpieza se ve más natural cuando tiene un singleton, a diferencia de una clase estática que contiene campos de estado estáticos.

El código, sin embargo, tendrá el mismo aspecto en cualquier caso, así que si tiene más razones específicas para preguntar, quizás deba explicarlo más detalladamente.

0

Los dos pueden ser bastante similares, pero recuerde que el verdadero Singleton debe en sí ser instanciado (concedido, una vez) y luego ser atendido.Una clase de base de datos PHP que devuelve una instancia de mysqli no es realmente un Singleton (como lo llaman algunas personas), porque devuelve una instancia de otra clase, no una instancia de la clase que tiene la instancia como miembro estático.

Por lo tanto, si está escribiendo una nueva clase que planea permitir solo una instancia de en su código, también podría escribirla como Singleton. Piense en ello como escribir una clase de Java simple y agregarla para facilitar el requisito de instancia única. Si está utilizando la clase de otra persona que no puede modificar (como mysqli), debe utilizar una clase estática (incluso si no puede prefijar su definición con la palabra clave).

0

Los singleton son más flexibles, lo que puede ser útil en los casos en que desee que el método Instance devuelva diferentes subclases concretas del tipo de Singleton en función de algún contexto.

0

Las clases estáticas no se pueden pasar como argumentos; las instancias de un singleton pueden ser. Como se menciona en otras respuestas, observe los problemas de subprocesamiento con clases estáticas.

rp

0

A singleton puede tener un constructor y el destructor. Dependiendo de su idioma, el constructor puede ser llamado automáticamente la primera vez que se utiliza su singleton, o nunca si su singleton no se utiliza en absoluto. Una clase estática no tendría tal inicialización automática.

Una vez que se obtiene una referencia a un objeto singleton, se puede utilizar como cualquier otro objeto. El código de cliente que ni siquiera necesita para conocer su uso de un producto único si una referencia a la singleton se almacena antes en:

Foo foo = Foo.getInstance(); 
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton 

Obviamente, esto facilita las cosas cuando se decide abandonar el patrón Singleton a favor de un verdadero patrón , como IoC.

0

Utilice el patrón de singleton cuando necesite calcular algo en tiempo de ejecución que podría calcular en tiempo de compilación si pudiera, como tablas de búsqueda.

4

Piense en un singleton como un servicio. Es un objeto que proporciona un conjunto específico de funcionalidades. P.ej.

ObjectFactory.getInstance().makeObject(); 

La fábrica de objetos es un objeto que realiza un servicio específico.

Por el contrario, una clase llena de métodos estáticos es una colección de acciones que es posible que desee realizar, organizadas en un grupo relacionado (La clase). P.ej.

StringUtils.reverseString("Hello"); 
StringUtils.concat("Hello", "World"); 

El ejemplo de StringUtils aquí es una colección de funcionalidades que se puede aplicar en cualquier lugar. El objeto de fábrica singleton es un tipo específico de objeto con una responsabilidad clara que puede crearse y pasarse donde se requiera.

7

Una de mis discusiones favoritas sobre este tema es here (sitio original abajo, ahora vinculado a Internet Archive Wayback Machine.)

Para resumir las ventajas de flexibilidad de un Singleton:

  • un Singleton se puede convertir fácilmente en una fábrica
  • un Singleton puede ser fácilmente modificado para volver diferente subclases
  • esto puede El resultado es una aplicación más fácil de mantener
4

Las clases estáticas son instanciadas d en tiempo de ejecución. Esto podría llevar mucho tiempo. Singletons se pueden crear instancias solo cuando sea necesario.

+12

Los Singletons también se instancian en tiempo de ejecución ... – recursive

+0

@recursive: la instanciación de Singleton se puede controlar. –

+3

quizás una palabra mejor sería inicialización (en lugar de creación de instancias) – Marlon

0

Creo que un lugar donde Singleton tendrá más sentido que la clase estática es cuando tiene que construir un grupo de recursos costosos (como conexiones de bases de datos). No le interesaría crear el grupo si nadie alguna vez lo usa (la clase estática significa que usted hace el trabajo costoso cuando se carga la clase).

5

Una clase estática con una carga de variables estáticas es un poco un truco.

/** 
* Grotty static semaphore 
**/ 
public static class Ugly { 

    private static int count; 

    public synchronized static void increment(){ 
     count++; 
    } 

    public synchronized static void decrement(){ 
     count--; 
     if(count<0) { 
      count=0; 
     } 
    } 

    public synchronized static boolean isClear(){ 
     return count==0;  

    } 
    } 

Un singleton con una instancia real es mejor.

/** 
* Grotty static semaphore 
**/ 
public static class LessUgly { 
    private static LessUgly instance; 

    private int count; 

    private LessUgly(){ 
    } 

    public static synchronized getInstance(){ 
    if(instance==null){ 
     instance = new LessUgly(); 
    } 
    return instance; 
    } 
    public synchronized void increment(){ 
     count++; 
    } 

    public synchronized void decrement(){ 
     count--; 
     if(count<0) { 
      count=0; 
     } 
    } 

    public synchronized boolean isClear(){ 
     return count==0;  

    } 
    } 

El estado está SÓLO en la instancia.

Por lo que el singleton se puede modificar más adelante para hacer agrupaciones, instancias locales de subprocesos, etc. Y ninguno de los códigos ya escritos debe cambiar para obtener el beneficio.

public static class LessUgly { 
     private static Hashtable<String,LessUgly> session; 
     private static FIFO<LessUgly> freePool = new FIFO<LessUgly>(); 
     private static final POOL_SIZE=5; 
     private int count; 

     private LessUgly(){ 
     } 

     public static synchronized getInstance(){ 
     if(session==null){ 
      session = new Hashtable<String,LessUgly>(POOL_SIZE); 
      for(int i=0; i < POOL_SIZE; i++){ 
       LessUgly instance = new LessUgly(); 
       freePool.add(instance) 
      } 
     } 
     LessUgly instance = session.get(Session.getSessionID()); 
     if(instance == null){ 
      instance = freePool.read(); 
     } 
     if(instance==null){ 
      // TODO search sessions for expired ones. Return spares to the freePool. 
      //FIXME took too long to write example in blog editor. 
     } 
     return instance; 
     }  

Es posible hacer algo similar con una clase estática, pero no habrá gastos generales por llamada en el despacho indirecta.

Puede obtener la instancia y pasarla a una función como argumento. Esto permite que el código se dirija al singleton "derecho". Sabemos que solo necesitarás uno ... hasta que no lo hagas.

La gran ventaja es que los singleton stateful se pueden hacer seguros para subprocesos, mientras que una clase estática no puede, a menos que lo modifique para ser un singleton secreto.

4

Los Singletons no se deben utilizar de la misma manera que las clases estáticas.En esencia,

MyStaticClass.GetInstance().DoSomething(); 

es esencialmente el mismo que

MyStaticClass.DoSomething(); 

Lo que realmente debería estar haciendo es tratar el singleton como un objeto más. Si un servicio requiere una instancia de la clase Singleton, a continuación, pasar a esa instancia en el constructor:

var svc = new MyComplexServce(MyStaticClass.GetInstance()); 

El servicio no debe tener en cuenta que el objeto es un producto único, y debe tratar el objeto como sólo un objeto.

El objeto ciertamente puede implementarse, como un detalle de implementación y como un aspecto de la configuración general, como un singleton si eso facilita las cosas. Pero las cosas que usan el objeto no deberían tener que saber si el objeto es un singleton o no.

0

Un singleton también es una buena idea si desea forzar el almacenamiento en memoria caché eficiente de datos. por ejemplo, tengo una clase que busca definiciones en un documento xml. Como el análisis del documento puede llevar un tiempo, configuré un caché de definiciones (utilizo SoftReferences para evitar outOfmemeoryErrors). Si la definición deseada no está en la caché, realizo el costoso análisis xml. De lo contrario, devuelvo una copia del caché. Como tener múltiples cach significaría que aún tendría que cargar la misma definición varias veces, necesito tener un caché estático. Elijo implementar esta clase como singleton para poder escribir la clase utilizando solo miembros de datos normales (no estáticos). Esto me permite seguir creando una istantiation de la clase si la necesito por alguna razón (serialización, pruebas unitarias, etc.)

13

¿Qué tal "avoid both"? Singleton y clases estáticas:

  • puede introducir el estado global
  • Consigue una estructura rígida a varias otras clases
  • Ocultar dependencias
  • Puede hacer clases de pruebas unitarias en forma aislada difícil

lugar, buscar en las bibliotecas Dependency Injection y Inversion of Control Container. Varias de las bibliotecas de IoC manejarán la administración de por vida para usted.

(Como siempre, hay excepciones, tales como clases de matemáticas estáticas y C métodos # de extensión.)

+1

Pequeñas liendres: las clases singleton son compatibles con las técnicas de inyección de dependencia (simplemente inyéctelas en sus clases dependientes y no es necesario que codifiquen nada), lo que permite realizar burlas y pruebas de forma aislada. También son un patrón de diseño válido para administrar recursos que se sabe que tienen una plataforma limitada. (El ejemplo clásico son las impresoras que no tienen administración de contención). – cdleary

+0

@cdleary - agreed; sin embargo, la implementación clásica a menudo deja Singleton.getInstance() en toda la base de código. Los "Singletons" para administrar recursos, cachés, etc. se pueden implementar con POCOs/POJOs y frameworks IoC Container que soportan administración de por vida (registrar el tipo de vida del contenedor y cada resolución obtendrá la misma instancia). – TrueWill

+9

Si desea dar a sus Singletons un entierro adecuado, vaya a http://www.singletonfuneralservice.com/ – TrueWill

2

patrón Singleton se utiliza generalmente para instancia de servicio de datos independientes o estáticas que múltiples hilos pueden acceder a los datos al mismo tiempo. Un ejemplo puede ser códigos de estado.

0

Singleton es como un servicio, como ya se mencionó. Pro es su flexibilidad. Estático, bueno, necesita algunas partes estáticas para implementar Singleton.

Singleton tiene un código para tener en cuenta la creación de instancias del objeto real, lo que puede ser de gran ayuda si tiene problemas de carreras. En una solución estática, es posible que tenga que lidiar con problemas de carreras en ubicaciones de códigos múltiples.

Sin embargo, al igual que Singleton se puede construir con algunas variables estáticas, es posible que pueda compararlo con 'goto'. Puede ser muy útil para construir otras estructuras, pero realmente necesita saber cómo usarlo y no debe "abusar" de él.Por lo tanto, la recomendación general es apegarse a Singleton y usar estática si es necesario.

También puedes ver el otro post: Why choose a static class over a singleton implementation?

0

refieren this

Resumen:

a. Una regla fácil que puede seguir es si no necesita mantener el estado, puede usar una clase estática; de lo contrario, debería usar un Singleton.

b. usar un Singleton es si es un objeto particularmente "pesado". Si su objeto es grande y ocupa una cantidad razonable de memoria, muchas llamadas n/w (grupo de conexiones) ... etc. Para asegurarse de que no se va a instanciar varias veces. Una clase Singleton ayudará a evitar que este caso ocurra

Cuestiones relacionadas