2010-06-03 21 views

Respuesta

22

Una buena razón para preferir un singleton a una clase estática (suponiendo que no haya mejores patrones a su disposición;)), es intercambiar una instancia de singleton con otra.

Por ejemplo, si tengo una clase de registro de la siguiente manera:

public static class Logger { 
    public static void Log(string s) { ... } 
} 

public class Client { 
    public void DoSomething() { 
     Logger.Log("DoSomething called"); 
    } 
} 

Funciona muy bien, pero lo que si registrador escribe cosas a una base de datos, o escribe a la consola.Si está escribiendo pruebas, probablemente no quiera todos esos efectos secundarios, pero como el método de registro es estático, no puede hacer nada excepto.

Bien, así que quiero intercambiar en caliente mi método de registro para probar. ¡Ve a buscar el gadget singleton!

public class Logger { 
    private static Logger _instance; 
    public static Logger Instance 
    { 
     get 
     { 
      if (_instance == null) 
       _instance = new Logger(); 
      return _instance; 
     } 
     set { _instance = value; } 
    } 
    protected Logger() { } 
    public virtual void Log(string s) { ... } 
} 

public class Client { 
    public void DoSomething() { 
     Logger.Instance.Log("DoSomething called"); 
    } 
} 

Así se puede definir una TestLogger : Logger con un método vacío Log, a continuación, establecer una instancia de su registrador de prueba a la instancia singleton para las pruebas. ¡Presto! Puede enrutar su implementación de registrador para pruebas o producción sin afectar el código del cliente.

10

Singleton se prefieren a menudo a las variables globales porque:

  • No contaminan el espacio de nombres global (o, en los idiomas con espacios de nombres, que contiene su espacio de nombres) con las variables innecesarias.
  • Permiten asignación e inicialización diferidas, mientras que las variables globales en muchos idiomas siempre consumirán recursos.

Source

EDIT:

Un uso fresco del singleton es decir, cuando se combina con el método de fábrica, se puede utilizar para crear la Flyweight pattern. Esto es cuando crea un nuevo objeto, Factory (en lugar de crear un nuevo objeto) comprueba primero para ver que una sola parte de ese objeto ya está hecha, si lo está, simplemente devuelve ese objeto; si no, crea un nuevo singleton. y lo devuelve, haciendo un seguimiento de los singletons que crea. Los pesos flotantes funcionan debido a la inmutabilidad del singleton.

+1

peso mosca es más como un "Multiton", no es realmente un producto único. – BalusC

+0

Multiton ... ¡Me gusta! –

+2

Sí existe. Ver [wikipedia] (http://en.wikipedia.org/wiki/Multiton_pattern). – BalusC

2

Singleton preservar el enfoque de clase convencional, y no requieren que se utiliza la palabra clave estática en todas partes. Pueden ser más exigentes de implementar al principio, pero simplificarán en gran medida la arquitectura de su programa. A diferencia de las clases estáticas, podemos usar singletons como parámetros u objetos.

Además, puede usar singletons con interfaces como cualquier otra clase.

3

A pesar de que en mi humilde opinión el patrón Singleton es un patrón bastante usado en exceso, lo hace a veces ofrecen beneficios, tales como:

  • La capacidad de utilizar diferentes tipos de objetos (que heredan de la misma base) como la instancia (piense en proveedores de datos donde uno usa el sistema de archivos y uno en una base de datos SQL, por ejemplo)
  • Serializabilidad. No he usado un marco que pueda serializar automáticamente clases estáticas.
  • Uso de campos menos estáticos. Para algunas personas esto es más una característica estética, pero en algunos casos tiene beneficios prácticos.
5

Singletons siempre me pareció un poco redundante. Prefiero clases estáticas, y si necesito un comportamiento diferente, lo combino con una inyección de dependencia y un proveedor. No sé qué patrón es, o si tiene un nombre, pero por lo general es algo como esto:

public interface IFooProvider { 
    Bar FooBar(); 
} 

public static class Foo { 
    public static readonly IFooProvider FooProvider { get; set; } 
    public Bar FooBar() { return FooProvider.FooBar(); } 
} 

Entonces sólo asegúrese de establecer el proveedor en algún lugar de mi método init. Es fácil agregar una inicialización lenta si lo desea estableciendo el proveedor predeterminado en la inicialización de la clase. Lo mejor de todo es que le permite cambiar el comportamiento sin perder la estética del uso de clases estáticas.

1
  1. Un Singleton puede implementar interfaces, heredar de otras clases
  2. Un Singleton se puede inicializar con pereza o asincrónica y se cargan automáticamente por el .NET Framework CLR (Common Language Runtime) cuando el programa o espacio de nombres que contiene la clase es cargado. Mientras que una clase estática generalmente se inicializa cuando se carga por primera vez y dará lugar a posibles problemas de cargador de clases.
  3. La clase Singleton sigue los Principios Orientados a Objetos
  4. Objetos Singleton almacenados en el montón mientras la clase estática se almacena en la pila.
  5. Los objetos Singleton pueden tener constructor mientras que la clase estática no.
  6. Singleton Los objetos pueden disponer, pero no de clase estática
  7. Singleton Los objetos pueden clonar pero no con la clase estática
Cuestiones relacionadas