2010-06-03 19 views
33

Quando un singleton sarebbe effettivamente più semplice o migliore di una classe statica? Mi sembra che creare un singleton sia solo uno sforzo extra che non è effettivamente necessario, ma sono sicuro che c'è una buona ragione. Altrimenti, non verrebbero usati, ovviamente.Perché utilizzare singleton anziché statico?

risposta

22

Una buona ragione per preferire un singleton rispetto a una classe statica (supponendo che non si disponga di modelli migliori a propria disposizione;)), sta sostituendo un'istanza singleton con un'altra.

Per esempio, se ho una classe di registrazione come questo:

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

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

Funziona davvero bene, ma cosa succede se Logger scrive cose da un database o scrive l'output alla console.Se stai scrivendo dei test, probabilmente non vuoi tutti quegli effetti collaterali, ma dal momento che il metodo log è statico, non puoi fare nulla se non.

Ok, quindi voglio scambiare a caldo il mio metodo Log per il test. Vai a 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"); 
    } 
} 

Così si può definire un TestLogger : Logger con un metodo vuoto Log, quindi impostare un'istanza del vostro registratore di prova per l'istanza Singleton per le prove. Presto! È possibile eseguire il hotswap dell'implementazione del logger per i test o la produzione senza influire sul codice client.

10

Singletons sono spesso preferiti a variabili globali perché:

  • Non inquinano lo spazio dei nomi globale (o, in lingue con spazi dei nomi, il loro spazio dei nomi che contiene) con le variabili non necessarie.
  • Permettono allocazioni e inizializzazioni pigre, mentre le variabili globali in molte lingue consumano sempre risorse.

Source

EDIT:

Un uso fresco del Singleton è, in combinazione con il metodo di fabbrica, può essere utilizzato per creare il Flyweight pattern. Questo è quando crei un nuovo oggetto, la Fabbrica (invece di creare un nuovo oggetto) prima controlla che un singleton di quell'oggetto sia già stato creato, se lo è, restituisce semplicemente quell'oggetto, altrimenti crea un nuovo singleton e restituisce ciò, tenendo traccia dei singleton creati. I pesi tondi funzionano a causa dell'immutabilità del singleton.

+1

mosca è più simile a un "multiton", non proprio un Singleton. – BalusC

+0

Multiton ... Mi piace! –

+2

Esiste. Vedi [wikipedia] (http://en.wikipedia.org/wiki/Multiton_pattern). – BalusC

2

Singoletti preservare l'approccio di classe convenzionale, e non richiedono di utilizzare la parola chiave static ovunque. All'inizio potrebbero essere più difficili da implementare, ma semplificheranno enormemente l'architettura del tuo programma. A differenza delle classi statiche, possiamo usare i singleton come parametri o oggetti.

Inoltre, è possibile utilizzare singleton con interfacce come qualsiasi altra classe.

3

Anche se secondo me il pattern Singleton è un modello piuttosto abusato, lo fa a volte offrono vantaggi, come ad esempio:

  • La possibilità di utilizzare diversi tipi di oggetti (che ereditano dalla stessa base), come l'istanza (si pensi ai provider di dati in cui si utilizza il filesystem e un database SQL, ad esempio)
  • Serializzabilità. Non ho usato un framework che può serializzare automaticamente le classi statiche.
  • Utilizzo di campi meno statici. Per alcune persone questa è più una caratteristica estetica, ma in alcuni casi ha vantaggi pratici.
5

I singleton mi sono sempre sembrati un po 'ridondanti. Preferisco le classi statiche e, se ho bisogno di un comportamento diverso, lo combino con un'iniezione di dipendenze e un fornitore. Non so quale modello sia, o se abbia un nome, ma di solito va in questo modo:

public interface IFooProvider { 
    Bar FooBar(); 
} 

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

Quindi mi limito a impostare il provider da qualche parte nel mio metodo init. È abbastanza facile aggiungere un'inizializzazione pigra, se si desidera, impostando il provider predefinito durante l'inizializzazione della classe. Meglio di tutti, ti permette di cambiare il comportamento mentre ottieni l'estetica dell'uso di classi statiche.

1
  1. Un Singleton può implementare interfacce, ereditare dalle altre classi
  2. Un Singleton può essere inizializzato pigramente o asincrono e caricato automaticamente da .NET Framework CLR (Common Language Runtime) quando il programma o il namespace che contiene la classe è caricato. Mentre una classe statica viene generalmente inizializzata quando viene caricata per la prima volta e porterà a potenziali problemi con il programma di caricamento classi.
  3. La classe Singleton segue i principi orientati agli oggetti
  4. Singleton Oggetti memorizzati su heap mentre la classe statica è memorizzata nello stack.
  5. Gli oggetti Singleton possono avere un costruttore mentre la classe statica non può.
  6. Singleton Gli oggetti possono disporre, ma non di classe statica
  7. Singleton Gli oggetti possono clonare, ma non con classe statica
Problemi correlati