2009-06-17 6 views
6

Ich hatte noch eine Interviewfrage. Ich dachte, das wäre albern, aber vielleicht fehlt mir etwas. Die Frage wurde gestellt, welches GoF-Muster das ist (Antwort: Singleton), und wenn es irgendwelche Probleme gibt, wie löse ich sie.Singleton Code-Auszug, eine Interview-Frage

Ich sehe keine Probleme. Ich habe erwähnt, dass das niemals freigegeben wird und ich erwarte das von diesem Muster. Das ist alles was ich gesagt habe. Fehle ich etwas?

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

Antwort

16

Thread-Sicherheit - Mehrere Instanzen können erstellt werden, wenn GetInstance() von konkurrierenden Threads aufgerufen wird.

3

Sie haben eine potenzielle Racebedingung in Multithread-Code. Zwei Threads können jeweils die Null-Überprüfung durchlaufen, bevor der Konstruktor des anderen Threads abgeschlossen ist, sodass beide die Klasse konstruieren können.

1

Es besteht ein potenzielles Problem, wenn Sie eine Multithread-Anwendung haben. Dies kann dazu führen, dass mehr als eine Instanz erstellt wird, wenn zwei Threads gleichzeitig angefordert werden.

Ich würde diese Seite auf Singletons in C# betrachten. Es zeigt das Problem im Detail, sowie bessere Optionen.

13

Siehe: An obvious singleton implementation for .NET?

Es gibt mehrere Bedenken, die Sie betrachten wollen, wenn ein Singleton-Muster zu implementieren.

  • Was passiert, wenn mehrere Anrufer Anfrage der Singleton von mehrere Threads. Es sollte einfach funktionieren.
  • Wann wird die Singleton Instanz Konstruktor aufgerufen. Vielleicht möchten Sie es so verzögern, dass es beim ersten Aufruf des Singletons passiert, Sie möchten vielleicht, dass es zu einem anderen Zeitpunkt instanziiert wird.
  • Sollten Menschen in der Lage sein von Ihrer Singleton-Klasse zu erben? Wie soll das Verhalten sein?
  • Sollte es möglich sein, Ihre Singleton-Instanz in eine andere Instanz zu wechseln, nachdem das Singleton instanziiert wurde. Wenn Sie dies bejahen, verletzt dies das Singleton-Muster, so dass das Feld, das Singletons enthält, im Allgemeinen readonly sein sollte.
  • API-Design, sollten Sie eine Eigenschaft oder Methode verwenden, um die Singleton-Instanz zurückzugeben.
  • Einige Leute sagen Singletons sind böse. Sollten Sie überhaupt darüber nachdenken. Dies wurde oft diskutiert ein guter Ausgangspunkt ist http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx

Das folgende ist ein gutes allgemeines Muster, das Sie folgen könnten. Sein Thread sicher, versiegelt, nutzt Eigenschaften und verzögert das 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

Der Code ist nicht threadsicher.Um es zu machen, damit Sie dies tun müssen, um:

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 ; 
    } 
} 

Dies ist der effizienteste Weg, der träge Laden der Instanz, da sie nur sperren stört (kann teuer werden), wenn vermutet wird, wird die Instanz nicht instanziiert werden für den nächsten Anruf. Durch nochmaliges Überprüfen der Sperre wird sichergestellt, dass sie nur einmal instanziiert wird.

+0

+1 ... obwohl ich persönlich nicht typeof (Class1) zum Sperren verwenden würde, sondern nur eine Objektinstanz, die für nichts anderes verwendet wird. –

+3

Ich bin absolut mit Fredrik Mörk - das Sperren eines Typenobjekts ist wirklich eine schlechte Übung (wie das Sperren ist). Jeder Code kann Sie (auch über App-Domains hinweg) sperren, wenn Sie Typobjekte sperren (und jeder Code, der Zugriff auf eine Instanz hat, kann Sie sperren, wenn Sie diesen sperren). Sperre (typeof (Class1)) {Class1.GetInstance(); } und Sie sind in ernsthaften Schwierigkeiten ... –

+0

Garry, siehe das Muster in meiner Antwort, seine Art und Weise sauberer IMHO –

0

so ist die Lösung die folgende?

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

Dies ist gut, aber auf das absolute Minimum oInstance sollte readonly und es nicht aufschieben Laden Sie die Singleton ... –

6

Andere erwähnten Fadensicherheit. Es gibt auch die Tatsache, dass sie vergessen haben, es als sealed zu markieren, und so könnten Sie davon erben und mehrere Instanzen auf diese Weise erstellen.

+0

+1 Ich habe diese Sorge in meine Antwort zusammengerollt –

+0

Nicht verhindert der private Standardkonstruktor Unterklassenbildung? – Andrew

+0

@Andrew ... Nein, es nicht, versuchen Sie es selbst ... –

0

Nicht bei dieser Firma arbeiten. Das Singleton-Muster ist kein häufig verwendetes Muster und seine Anwendbarkeit in einem reinen OO-System ist fraglich. Das Rückgängigmachen eines Singleton-Musters ist ein großes Problem, wenn Sie es jemals wieder in ein normal konstruiertes Objekt zurückdrehen müssen.

+0

Das ist eine sehr breite Aussage. Ich denke, es hängt davon ab, welche Art von Entwicklung du tust. Mein Team schreibt Systemsoftware in C++ und Java und Singletons werden HEAVILY in beiden verwendet. – xeon

+0

Es ist eine breite Aussage, aber im Allgemeinen mag ich heute all meine Abhängigkeiten in einem Kernel, der all diese Abhängigkeiten verwaltet, anstatt alle meine Abhängigkeiten über meine App zu verteilen. Ein Singleton macht das Testen sehr viel schwieriger. –

+0

Ich dachte, das könnte auch wahr sein, bis ich merkte, dass sie bei meinem aktuellen Projekt sehr nützlich waren ... im Grunde ist es eine Frage der Instanziierung, manchmal will man wirklich nur eine Instanz Ihres Objekts und nicht mehr. – alchemical