2014-10-22 18 views
7

Ich erkannte, dass ich nur eine Instanz eines Objekts namens StdSchedulerFactory auf einmal ausgeführt haben sollte. Bisher instanziiert ich das Objekt wie dieseSingleton-Klasse für ein Objekt mit Parametern

StdSchedulerFactory sf = new StdSchedulerFactory(properties); 

Und Eigenschaften ist ein NameValueCollection. Wie kann ich eine Singleton-Klasse für dieses Objekt schreiben, so dass die Variable sf immer eine Instanz im gesamten Programm haben wird?

+1

Sind Sie fragen [Wie ein Singleton implementieren] (http://msdn.microsoft.com/en-us/library/ff650316.aspx) oder [Beispiele ] (http://www.dotnetperls.com/singleton) – alykins

+0

Was würde passieren, wenn jemand einen zweiten instanziiert? Wäre es so schlimm, dass Sie lieber keinen richtigen Komponententest haben würden? – nvoigt

+0

@nvoigt Es ist durchaus möglich, einen Singleton zu testen, es muss nur eine Schnittstelle abgeleitet werden; dann können Sie es für das Testen anderer Objekte verspotten, und wenn Sie * es * testen, ist es ein Singleton egal. (Beachten Sie, dass Sie einen DI-Container benötigen, damit dies funktioniert). – BradleyDotNET

Antwort

9

Ein Teil des Singleton Musters ist normalerweise ein privater Konstruktor, sodass andere Klassen keine neuen Instanzen erstellen können.

Die Abhilfe für Parameter kommen außerhalb der Klasse ist eine „Init“ oder „Configure“ Funktion hinzuzufügen:

public static void Configure(NameValueCollection properties) 
{ 
} 

Natürlich, wenn Sie diese Funktion aufrufen, vergessen, können Sie Verhalten, das Sie bekommen don nicht wollen; Vielleicht möchten Sie also ein "Configured" -Flag oder ähnliches setzen, damit Ihre anderen Funktionen angemessen reagieren können, wenn diese Funktion noch nicht aufgerufen wurde.

+0

Es tut mir leid, aber ich verstehe das nicht wirklich. Können Sie mir sagen, wie Ihre Konfigurationsfunktion in meinem Fall verwendet werden muss? – Disasterkid

+0

@ Pedram Es ist nur eine öffentliche Methode in der Singleton-Klasse. Sie nennen es irgendwann kurz vor dem Programmstart (vorzugsweise bevor irgendwelche Methoden aufgerufen werden, die vom Argument abhängen). – BradleyDotNET

+0

@BradleyDotNET ist dies manchmal etwas, das von einem Singleton benötigt wird, d. H. Das löst, was ich tun muss (+1), aber ich will nicht "gegen den Strich" gehen? Ist das eine ungewöhnliche Übung? – Thomas

1

Hier ist eine grundlegende Singleton-Implementierung. Es ist nicht Thread-Safe.

public sealed class StdSchedulerFactory 
{ 
    private static readonly StdSchedulerFactory instance; 
    private NameValueCollection _properties; 

    private StdSchedulerFactory(NameValueCollection properties) 
    { 
     _properties = properties; 
    } 

    public static StdSchedulerFactory GetInstance(NameValueCollection properties) 
    { 
     if (instance == null) 
     { 
     instance = new StdSchedulerFactory(properties); 
     } 
     else 
     { 
     return instance; 
     } 
    } 
} 
+1

Bemerkenswert ist jedoch, dass das Hinzufügen eines schreibgeschützten Objekts oben eine einfache Möglichkeit ist, es threadsicher zu machen (und die entsprechenden Sperren um Eigenschaften/Methoden). – alykins

+2

Wahrscheinlich wollten Sie Eigenschaften übergeben. Ich hasse dieses Muster ...Das bedeutet, dass ich eine Reihe von Eigenschaften übergebe, aber ich erhalte eine Instanz, die mit einer völlig ** anderen ** Menge von Eigenschaften erstellt wurde. Ich hasse Methoden, die mich belügen. – nvoigt

+0

yep, verpasste das. Ich stimme zu, es gibt bessere Wege. –

1

dies ist mein zwei Lieblingsweg, der einfaches singleton Muster einführt. Das zweite ist nur einfacher, wenn das Debuggen :)

public sealed class SingletonOne 
{ 
    private static readonly Lazy<SingletonOne> instance = new Lazy<SingletonOne>(() => new SingletonOne()); 

    private Lazy<Controller> controller = new Lazy<Controller>(() => new Controller(properties)); 

    private static object properties = null; 

    public static SingletonOne Instance { get { return instance.Value; } } 

    public Controller GetController(object properties) 
    { 
     SingletonOne.properties = properties; 

     return this.controller.Value; 
    } 
} 

public sealed class SingletonTwo 
{ 
    private static readonly SingletonTwo instance = new SingletonTwo(); 

    private Controller controller; 

    private static object properties = null; 

    public static SingletonTwo Instance 
    { 
     get 
     { 
      return SingletonTwo.instance; 
     } 
    } 

    public Controller GetController(object properties) 
    { 
     SingletonTwo.properties = properties; 

     if(this.controller == null) 
     { 
      this.controller = new Controller(SingletonTwo.properties); 
     } 

     return this.controller; 
    } 
} 

public class Controller 
{ 
    public Controller(object properties) { } 
} 
Verwandte Themen