wake-up-neo.net

Cosa c'è di alternativo a Singleton

Abbiamo una classe che contiene informazioni di configurazione per l'applicazione. Era un singleton. Dopo alcune revisioni architettoniche, ci è stato detto di rimuovere il singleton. Abbiamo riscontrato alcuni vantaggi di non utilizzare singleton nel test unitario perché possiamo testare diverse configurazioni contemporaneamente.

Senza singleton, dobbiamo passare l'istanza ovunque nel nostro codice. Sta diventando così disordinato, quindi abbiamo scritto un wrapper singleton. Ora stiamo trasferendo lo stesso codice su PHP e .NET, mi chiedo se esiste un modello migliore che possiamo usare per l'oggetto di configurazione.

113
John Mill

Google Testing blog contiene una serie di voci su come evitare Singleton (al fine di creare un codice testabile). Forse questo può aiutarti:

L'ultimo articolo spiega in dettaglio come spostare la creazione di nuovi oggetti in una fabbrica, in modo da poter evitare l'uso di singoli. Vale la pena leggere di sicuro.

In breve, trasferiamo tutti i nuovi operatori in una fabbrica. Raggruppiamo tutti gli oggetti di durata simile in un'unica fabbrica.

127
FrankS

Il modo migliore è invece utilizzare un modello Factory. Quando costruisci una nuova istanza della tua classe (in fabbrica) puoi inserire i dati "globali" nell'oggetto appena costruito, sia come riferimento a una singola istanza (che memorizzi nella classe di fabbrica) o copiando la relativa dati nel nuovo oggetto.

Tutti i tuoi oggetti conterranno quindi i dati che vivevano nel singleton. Non credo che ci sia molta differenza nel complesso, ma può rendere più facile la lettura del codice.

15
gbjbaanb

Potrei affermare l'ovvio qui, ma c'è un motivo per cui non è possibile utilizzare un framework di iniezione di dipendenza come Spring o Guice ? (Credo che anche Spring sia disponibile anche per .NET).

In questo modo, il framework può contenere una singola copia degli oggetti di configurazione e i tuoi bean (servizi, DAO, qualunque cosa) non devono preoccuparsi di cercarli.

Questo è l'approccio che di solito prendo!

5
user7094

non accumulare responsabilità verso un singolo oggetto di configurazione poiché finirà in un oggetto molto grande che è sia difficile da capire che fragile.

Ad esempio, se hai bisogno di un altro parametro per una particolare classe, cambi l'oggetto Configuration, quindi ricompila tutte le classi che lo usano. Questo è alquanto problematico.

Prova a refactoring del codice per evitare un oggetto Configuration comune, globale e grande. Passare solo i parametri richiesti alle classi client:

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

dovrebbe essere refactored per:

 class Server {

    public Server(int port) {
       this.port = port;
    }
 }

a framework di iniezione delle dipendenze aiuterà molto qui, ma non è strettamente necessario.

4
dfa

Se usi Spring Framework , puoi semplicemente creare un bean normale. Per impostazione predefinita (o se si imposta esplicitamente scope="singleton") Viene creata solo un'istanza del bean e tale istanza viene restituita ogni volta che il bean viene utilizzato in una dipendenza o recuperato tramite getBean().

Ottieni il vantaggio della singola istanza, senza l'accoppiamento del modello Singleton.

4
CoverosGene

L'alternativa è passare ciò di cui hai bisogno invece di chiedere un oggetto per le cose.

4
koen

È possibile ottenere lo stesso comportamento di singleton utilizzando metodi statici. Steve yegge lo spiega molto bene in questo post.

1
Youssef

Rivedere la possibilità di effettuare la configurazione come interfaccia di callback. Quindi il tuo codice sensibile alla configurazione apparirà:

MyReuseCode.Configure(IConfiguration)

Il codice di inizializzazione del sistema apparirà:

Library.init(MyIConfigurationImpl)
0
Dewfy

È possibile utilizzare un framework di iniezione delle dipendenze per alleviare il dolore del passaggio nell'oggetto di configurazione. Uno decente è ninject che ha il vantaggio di usare il codice piuttosto che xml.

0
Colin Gravill

È possibile una classe che contiene solo metodi e campi statici? Non sono sicuro di quale sia esattamente la tua situazione, ma potrebbe valere la pena esaminarlo.

0
Thomas Owens

Forse non è neanche molto pulito, ma potresti passare i bit di informazione che desideri siano cambiati nel metodo che crea il singleton - invece di usare

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

è possibile chiamare createSingleton(Information info) direttamente all'avvio dell'applicazione (e nei metodi setUp dei test unitari).

0
Roland Ewald

Dipende da quali strumenti/framework ecc. Vengono utilizzati. Con gli strumenti di iniezione delle dipendenze/ioc è spesso possibile ottenere prestazioni/ottimizzazioni singleton facendo in modo che il contenitore di/ioc utilizzi il comportamento singleton per la classe richiesta - (come un'interfaccia IConfigSettings) creando sempre e solo un'istanza della classe. Questo potrebbe essere ancora sostituito per il test

In alternativa, è possibile utilizzare una factory per creare la classe e restituire la stessa istanza ogni volta che viene richiesta, ma per il test potrebbe restituire una versione stub/beffata

0
saret