Domanda

Sono l'attuazione di un quadro di notifica per uno dei miei progetti. Come voglio che sia molto generico, l'utente può utilizzare diversi livelli di trasporto, in modo che egli non ha veramente bisogno di prendersi cura di usare un metodo di consegna (diciamo WCF) o un altro (per esempio, ActiveMQ). L'interfaccia utente ha accesso è ovviamente indipendente dal metodo di consegna (WCF o ActiveMQ). Eppure, le due classi (consumatori e produttori) implementa single, in modo che effettivamente utilizzano costruttori predefiniti (significato, senza parametri). Il mio problema è che mi piacerebbe avere un parametro, il metodo di consegna l'utente desidera utilizzare. Ma per quanto ne so, Singleton utilizzare solo costruttori di default? che è normale, non ci dovrebbe essere punto di usare singletons con parametri. Allora, quali sono le mie opzioni qui? non creare un Singleton? creare un metodo per impostare il metodo di consegna?

La ringrazio molto per il vostro aiuto,

Sebastian

È stato utile?

Soluzione

Si può certamente avere parametri con singletons, tranne che invece di passando il parametro in un costruttore, si sta passando nel metodo getInstance (). Il tuo costruttore sovrascritto deve essere privata, naturalmente, per una vera e propria implementazione Singleton. Il mio esempio è scritto in Java, ma vale per C # e.

Esempio:

Singleton s = Singleton.getInstance(42);

Nel codice Singleton:

private Singleton() {

}

private Singleton(int num) {
   //set num
}

public getInstance(int num) {
  //singleton code (calls the private non-default constructor if an object 
  //does not already exist) 
}

Altri suggerimenti

Ci sono alcuni quadri iniezione di dipendenza come Spring.Net che potrebbero aiutarvi. È possibile passare in modo efficace un parametro in un file di configurazione per il costruttore di single.

Link ad un esempio Spring Framework

Posso suggerire che se si hanno due diversi comportamenti richiesti del vostro Singleton che si potrebbe desiderare di sottoclasse. In questo modo si ottiene il comportamento che si desidera chiamando il Singleton del comportamento della classe che si desidera.

È possibile farlo facilmente con un quadro iniezione di dipendenza. Ho un costrutto simile nel mio progetto attuale utilizzando MEF . Tutto ciò che serve è quella di utilizzare le opzioni di iniezione costruttore, e aggiungere che il montaggio e l'assemblaggio della dipendenza richiesto al catalogo, e cavi sia corretta e funzionante.

Un'altra opzione è quella di avere una qualche forma di funzione di inizializzazione che prende la vostra scelta, e costruisce l'istanza Singleton. Invece di costruire sul primo accesso, è possibile costruire durante la chiamata di inizializzazione. Il rovescio della medaglia è che è necessario assicurarsi di inizializzare il Singleton prima di utilizzarlo (tipicamente all'avvio del programma, utilizzando un file di configurazione).

Una soluzione soggetto a errori simili, ma meno, è quello di avere solo il Singleton inizializzazione pigra, e dargli un'opzione "default". Consentire al chiamante di impostare una proprietà statica di alterare quale opzione è costruito, quindi se è impostato prima della costruzione del Singleton, si otterrà un predefinito diverso. Questo può creare confusione, però, dal momento che ancora una volta, è necessario assicurarsi di impostare la proprietà prima di accedere al Singleton, o avrai un comportamento imprevisto.

So che è tardi per rispondere alla domanda originale, ma ho appena avuto questo problema ed ecco come ho risolto. Potrebbe non essere l'ideale, ma sembra funzionare. Ho creato un metodo Init che deve essere chiamato prima di tentare di utilizzare l'istanza Singleton.

public void Init(/*parameters*/)
{
        if (_isInitialized)
        {
            throw new InvalidOperationException("Component is already initialized!");
        }
        //do your work here
}

Ogni altro accesso all'istanza Singleton (proprietà ottenere, insieme, le chiamate di metodo) sarà un'eccezione un'operazione non valida dire che l'oggetto non è stato inizializzato.

Credo che questo fa quello che mi serve, è meno confusione di GetInstance (params) perché non v'è alcun rischio di fraintendere ciò che il metodo fa. Il rovescio della medaglia è che non getterà errori di compilazione, ma la prima esecuzione, senza l'inizializzazione fatto sarà un'eccezione, quindi dovrebbe essere abbastanza buono.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top