2014-10-22 13 views
7

Mi sono reso conto che avrei dovuto eseguire una sola istanza di un oggetto chiamato StdSchedulerFactory alla volta. Finora ho istanziato l'oggetto come questoClasse Singleton per un oggetto con parametri

StdSchedulerFactory sf = new StdSchedulerFactory(properties); 

E proprietà è un NameValueCollection. Come posso scrivere una classe Singleton per questo oggetto in modo che la variabile sf abbia sempre un'istanza per tutto il programma?

+1

stai chiedendo [Come implementare un singleton] (http://msdn.microsoft.com/en-us/library/ff650316.aspx) o [Esempi ] (http://www.dotnetperls.com/singleton) – alykins

+0

Cosa accadrebbe se qualcuno creasse un secondo istante? Sarebbe così brutto che preferiresti non avere un vero test unitario invece? – nvoigt

+0

@nvoigt È perfettamente possibile testare un'unità singleton, è sufficiente ricavare un'interfaccia; allora puoi prenderlo in giro per testare altri oggetti, e quando lo testi * it *, essere singleton non ha importanza. (Nota che è necessario un contenitore DI per farlo funzionare). – BradleyDotNET

risposta

9

Parte del modello Singleton è in genere un costruttore privato, in modo che altre classi non possano creare nuove istanze.

La soluzione per i parametri provenienti dall'esterno della classe è di aggiungere una o la funzione "Init" "Configura":

public static void Configure(NameValueCollection properties) 
{ 
} 

Naturalmente, se si dimentica di chiamare questa funzione, è possibile ottenere un comportamento don non voglio; quindi potresti voler impostare un flag "Configurato" o qualcosa di simile in modo che le altre funzioni possano reagire in modo appropriato se questa funzione non è stata ancora chiamata.

+0

Mi dispiace ma non lo capisco davvero. Potresti dirmi come deve essere utilizzata la tua funzione Configure nel mio caso? – Disasterkid

+0

@Pedram È solo un metodo pubblico nella classe Singleton. Si chiama a volte vicino all'avvio del programma (preferibilmente prima che vengano chiamati tutti i metodi che dipendono dall'argomento). – BradleyDotNET

+0

@BradleyDotNET è qualche volta qualcosa che è richiesto da un Singleton, cioè questo risolve ciò che devo fare (+1), ma non voglio "andare controcorrente"? È una pratica rara? – Thomas

1

Ecco un'implementazione di base di Singleton. È non thread-safe.

+1

Vale la pena notare che l'aggiunta di un oggetto readonly in alto è un modo semplice per renderlo a prova di thread (e i blocchi appropriati attorno a proprietà/metodi). – alykins

+2

Probabilmente intendevi passare le proprietà. Odio questo modello ...questo significa che passo un set di proprietà, ma ottengo un'istanza creata con un insieme ** completamente diverso di proprietà. Odio i metodi che mi mentono. – nvoigt

+0

sì, perso quello. Sono d'accordo, ci sono modi migliori. –

1

questo è il mio modo preferito di implementare il semplice schema singleton. Il secondo è solo più facile quando il debug :)

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) { } 
}