2009-06-17 8 views
6

Ho avuto un'altra domanda di intervista. Pensavo fosse sciocco, ma forse c'è qualcosa che mi manca. La domanda ha chiesto quale pattern GoF sia (risposta: singleton) e, se ci sono problemi, come li risolvo.Estratto di codice di Singleton, un'interrogazione-domanda

Non vedo alcun problema. Ho detto che questo non è mai stato liberato e che mi aspetto da questo schema. Questo è tutto ciò che ho detto. Mi sto perdendo qualcosa?

public class Class1 
{ 
    private static Class1 oInstance = null; 
    private Class1() { } 
    public static Class1 GetInstance() 
    { 
     if (oInstance == null) 
     { 
      oInstance = new Class1(); 
     } 
     return oInstance ; 
    } 
} 

risposta

16

Sicurezza thread: è possibile creare più istanze se GetInstance() viene chiamato da thread concorrenti.

3

Hai una potenziale condizione di competizione nel codice multithread. Due thread potrebbero superare il controllo Null prima che il costruttore sull'altro thread sia completato, in modo che entrambi possano finire per costruire la classe.

1

C'è un potenziale problema con questo se si dispone di un'applicazione multithread. Ciò può causare la creazione di più di un'istanza se due thread richiedono allo stesso tempo.

Darei un'occhiata a questa pagina su Singletons in C#. Mostra il problema in dettaglio, oltre a opzioni migliori.

13

Vedi: An obvious singleton implementation for .NET?

ci sono più le preoccupazioni che si desidera prendere in considerazione in sede di attuazione di un pattern Singleton.

  • Cosa accade quando più chiamanti richiesta il singoletto da più thread. Dovrebbe funzionare.
  • Quando è chiamato il costruttore dell'istanza Singleton. Si consiglia di posticiparlo in modo che avvenga alla prima chiamata che richiede il singleton, potreste volerlo prima istanziare in un altro momento.
  • Le persone possono essere in grado di ereditare dalla classe singleton? Quale dovrebbe essere il comportamento?
  • Dovrebbe essere possibile passare l'istanza singleton a un'istanza diversa dopo l'istanza del singleton. Rispondendo sì a questo viola il modello singleton, quindi in generale i single singletons di campo dovrebbero essere in sola lettura.
  • Progettazione API, se si utilizza una proprietà o un metodo per restituire l'istanza Singleton.
  • Alcuni persone dicono singleton sono cattivi. Dovresti anche considerarlo in primo luogo. Questo è stato discusso abbastanza spesso un buon punto di partenza è http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx

Quanto segue è un buon schema generale che potreste seguire. Il suo filo sicuro, sigillato, usa le proprietà e rinvia instrada il singleton.

public sealed class Singleton 
{ 
    static class SingletonCreator 
    { 
     // This may seem odd: read about this at: http://www.yoda.arachsys.com/csharp/beforefieldinit.html 
     static SingletonCreator() {} 
     internal static readonly Singleton Instance = new Singleton(); 
    } 

    public static Singleton Instance 
    { 
     get { return SingletonCreator.Instance; } 
    } 
} 
3

Il codice non è thread-safe.Per fare in modo che devi fare questo:

public class Class1 
{ 
    private static Class1 oInstance = null; 
    private Class1() { } 
    public static Class1 GetInstance() 
    { 
     if (oInstance == null) 
     { 
      lock(typeof(Class1)) 
      { 
       if (oInstance == null) 
       { 
        oInstance = new Class1(); 
       } 
      } 
     } 
     return oInstance ; 
    } 
} 

Questo è il modo più efficiente di pigramente caricare l'istanza come dà fastidio solo per bloccare (può essere costoso) quando si sospetta non sarà istanziato l'istanza per la prossima chiamata. Il controllo di nuovo una volta nella serratura assicura che verrà istanziato una sola volta.

+0

+1 ... anche se personalmente non userò typeof (Class1) per il blocco, ma piuttosto solo un'istanza di oggetto che non viene utilizzata per nient'altro. –

+3

Sono assolutamente d'accordo con Fredrik Mörk: il blocco di un oggetto di tipo è una pratica veramente pessima (poiché il blocco è questo). Ogni codice può bloccarti (anche attraverso i domini) se blocchi gli oggetti di tipo (e ogni codice che ha accesso a un'istanza può bloccarti se lo stai bloccando). lock (typeof (Class1)) {Class1.GetInstance(); } e sei in guai seri ... –

+0

Garry, vedi lo schema nella mia risposta, il modo in cui pulisci IMHO –

0

quindi la soluzione è la seguente?

public class Class1 
{ 
    private static Class1 oInstance = new Class1(); 
    private Class1() { } 
    public static Class1 GetInstance() 
    { 
     return oInstance ; 
    } 
} 
+0

Questo è buono ma al minimo indispensabile oInstance deve essere di sola lettura e non differisce carica il singleton ... –

6

Altri citati sicurezza del filo. C'è anche il fatto che si sono dimenticati di contrassegnarlo come sealed, quindi si potrebbe ereditare da esso e creare più istanze in questo modo.

+0

+1 Ho inserito questo problema nella mia risposta –

+0

Il costruttore predefinito privato non impedisce la sottoclasse? – Andrew

+0

@Andrew ... no, no, provalo da te ... –

0

Non lavorare in quell'azienda. Il modello singleton non è uno schema usato frequentemente e la sua applicabilità in un puro sistema OO è discutibile. Annullare un modello singleton è un grosso problema se si ha la necessità di riattivarlo in un oggetto costruito normalmente.

+0

Questa è una dichiarazione molto ampia. Penso che dipenda dal tipo di sviluppo che fai. Il mio team scrive software di sistema in C++ e Java e Singletons sono utilizzati HEAVILY in entrambi. – xeon

+0

In generale, tuttavia, in generale in questi giorni mi piace rubare tutte le mie dipendenze in un kernel che gestisce tutte queste dipendenze invece di far sì che tutte le mie dipendenze si diffondano in tutta la mia app. Avere singletons rende i test molto più difficili. –

+0

Ho pensato che anche questo potesse essere vero, fino a quando ho realizzato che erano super utili nel mio progetto attuale ... fondamentalmente è una questione di istanziazione, a volte vuoi solo un'istanza del tuo oggetto e non più. – alchemical