2013-05-31 3 views
6

ho scoperto che in C# è possibile implementare una classe Singleton, come segue:implementazione Singleton classe ereditabile in C#

class Singleton 
{ 

    private static Singleton _instance; 

    public static Singleton Instance 
    { 
     get { return _instance ?? (_instance = new Singleton()); } 
    } 

    protected Singleton() { } 
} 

che lavora per le istanze di tipo Singleton, vale a dire:

var a = Singleton.Instance; 
var b = Singleton.Instance; 
Console.WriteLine(ReferenceEquals(a, b)); //Prints True. 

Ma cosa se voglio che le classi derivate di Singleton anche seguire il pattern Singleton, vale a dire:

class A:Singleton 
{ ... } 
A a = A.Instance; 

In questo caso l'elemento statico Instance è accessibile dalla classe Singleton e crea un'istanza Singleton, che non è l'obiettivo. Inoltre, ci sono due problemi principali con questa soluzione:

  • La classe derivata può implementare un proprio costruttore e slacciare il pattern Singleton.
  • Se v'è un altro esempio di Singleton allora la classe derivata sta per riferimento che meno di derivazione esempio

La mia domanda è: C'è un altro modo per implementare una classe Singleton in C# in modo che classe derivata sono anche singleton?

+0

domanda interessante, suggerisco di dare una lettura: http://msmvps.com/blogs/jon_skeet/archive/2006/01/20/singleton-inheritance.aspx –

risposta

17

Ignorando il solito "Non usare un Singleton, guarda il tuo disegno". argomenti, è, concettualmente, potrebbe implementare uno come questa convenzione (supponendo che le vostre classi derivate hanno costruttori di default):

public abstract class Singleton<T> where T : class, new() 
{ 
    private static T _instance; 

    public static T GetInstance() 
    { 
     if(_instance == null) 
      _instance = new T(); 
     return _instance; 
    } 
} 

E derivare questa convenzione:

public class SingletonA : Singleton<SingletonA> { /* .... */ } 
public class SingletonB : Singleton<SingletonB> { /* .... */ } 

Ma, io davvero non sostengo questo approccio Singleton personalmente. Hanno i loro (rari) usi, ma possono rivelarsi più dolorosi del barbone, trasformandosi in contenitori globali glorificati e variabili.

Inoltre, prestare attenzione alla sicurezza del filo.

+2

Sarei anche cauto nell'usare una proprietà di istanza piuttosto di un metodo GetInstance(). Ci sono alcune cose divertenti che possono accadere se si passa il mouse sopra la proprietà Instance nel debugger mentre si verifica un breakpoint a causa di un effetto collaterale dell'istanza costruita nel codice. Certo, è molto meglio a) evitare il modello Singleton eb) evitare effetti collaterali nei loro costruttori. –

+0

@DanBryant, assolutamente corretto - hanno modificato. –

+0

+1 per '" Non usare un Singleton, guarda il tuo disegno. "'. –

3

La mia domanda è: c'è un altro modo per implementare una classe Singleton in C# assicurando che anche le classi derivate siano singleton?

Beh, si potrebbe avere una sorta di controllo all'interno del costruttore che:

  • Il tipo effettivo di this è sigillato
  • Il tipo effettivo di this è una sottoclasse diretta di Singleton
  • Nessun'altra istanza di quel tipo è stata creata (mantenendo un HashSet<Type>)

Tuttavia, sembra piuttosto inutile. Qual è in realtà la tua classe base destinata a raggiungere?

Il modello singleton è easy to implement properly (che il vostro esempio non è, a proposito - non è thread-safe) quindi perché avere la classe base? La classe base stessa non sarebbe un singleton (ci sarebbero potenzialmente molte istanze - una per sottoclasse) quindi qual è il vantaggio?

Mi sembra che "Sono un singleton per il tipo effettivo dell'oggetto" non è una base appropriata per l'ereditarietà in primo luogo, e sinceramente cerco di evitare il modello singleton fino a possibile comunque.

Se si desidera realmente una classe base, dovrebbe essere perché esistono alcune funzionalità comuni che tutte le sottoclassi ereditano naturalmente. È improbabile che sia inerentemente da stabilire se queste sottoclassi sono singleton.