2010-01-17 19 views
10

Eventuali duplicati:
On Design Patterns: When to use the Singleton?Quali sono alcuni usi legittimi specifici per i singleton?

Questa domanda non è se o no single sono "considerati nocivi" in generale. Voglio solo sapere, dalla tua esperienza, quali sono le SITUAZIONI SPECIFICHE in cui i singleton sembrano funzionare bene.

EDIT: domande Per favore, se si vuole discutere l'opportunità e/o malvagità del singletons in generale, ci sono aleady exising: 137975, 11831

Ops! Ho appena scoperto che la mia domanda è già stata posta qui: On Design Patterns: When to use the Singleton?

+2

La domanda è mal formulata, i singleton sembrano funzionare bene in molte situazioni. Dovrebbe essere "quando le variabili globali sono buone"? –

+0

@just somebody: lascerò che le persone interpretino "singleton" come vogliono. :) –

risposta

7

Fondamentalmente li usiamo per due cose: registrazione e configurazione . Entrambi presuppongono che l'app abbia una configurazione centrale e un file di log centrale, non sempre valida ma nella maggior parte del nostro codice. Li usiamo anche occasionalmente per determinate classi di fabbrica o classi di cache che vogliamo assicurarsi che non stiamo duplicando i metadati chiave.

1

C'è un singolo dispositivo/hardware collegato al sistema e un punto centrale di controllo è necessario per usarlo correttamente.

+5

Ho visto alcune "premature singletonization" nei sistemi embedded in cui il driver per una porta di comunicazione supportava solo un'istanza. Successivamente, quando sono diventate disponibili più porte di comunicazione, il driver doveva essere revisionato per supportare più istanze. Alcune parti del codice dell'applicazione che utilizzavano il driver della porta di comunicazione necessitavano anche di una riscrittura. Mi chiedo, quale dispositivo sarebbe sempre veramente unico e non avrà mai più istanze? –

+0

Direi anche di non usare un singleton per l'hardware. Altrimenti non è possibile testare il codice separatamente dall'hardware. Meglio creare un'interfaccia. Posso vedere un singleton essere utile se hai bisogno di scrivere sull'hardware da molti punti diversi del tuo codice, ma mi sembra che sia un design scadente. –

0

ho lavorato duramente per sbarazzarsi di Singoletti nel progetto corrente sto lavorando. Hanno un odore, ma a volte sono molto difficili da evitare.

La mia situazione era che avevo un'API che costruiva oggetti singleton per gestire le funzioni di gestione come Sicurezza, Configurazione, ecc. L'API usava EntityFramework e inseriva anche PlugIn (usando MEF). Poiché la costruzione di queste classi non è sempre stata eseguita dal mio codice (in particolare per le entità EF), non è stato sempre possibile iniettarle elegantemente in oggetti biz. Quindi ho usato i singleton, a cui è possibile accedere ovunque all'interno di un progetto soggetto a portata dell'erede.

-1

sono buoni per gli elementi che si desidera considerare come risorse uniche.

A titolo di esempio in sistemi web si potrebbe desiderare di utilizzare solo una connessione al database unico per ogni pagina che è servita - in questo caso utilizzando il pattern Singleton avrebbe senso. (Anche se dovresti codificare con la consapevolezza che l'oggetto di accesso al database era un singleton, che è meno ideale, ma accettabile se chiaramente documentato, ecc.)

-1

Quando una parte del programma richiede un oggetto che implementa un'interfaccia specifica (polimorfismo-saggio), ma non si desidera mai più di una singola istanza di tale oggetto. In caso contrario, i metodi statici lo faranno.

0

Il server master riceve richieste dai client e inoltra tali richieste a un processo subordinato. Il processo subordinato può utilizzare un singleton per comunicare con il server principale.

+1

I downvotes non commentati sono davvero fastidiosi. Descrivo un modello utilizzato in Postfix: il server master Postfix gestisce i percorsi di connessione tra tutti gli altri eseguibili nel sistema. Se una sotto parte del sistema ha bisogno di parlare con un altro, è necessario utilizzare il server principale per scoprire come. –

+0

(il downvote non è il mio) è possibile eseguire più istanze Postfix su una singola macchina => il master non è un Singleton. in più non sarebbe un valido motivo per utilizzare il modello nell'implementazione del subordinato, IMO. –

+0

Il master non è un singleton e non penso di descriverlo come tale. Ogni singolo processo subordinato ha una connessione singleton al master specifico che lo controlla. Non ha senso che un subordinato abbia più maestri. –

0

Cerco di non fare affidamento su Singleton, tuttavia preferisco disaccoppiare a non usare Singleton. Pertanto, spesso uso Singleton abbinato al pattern Prototype, che consente la registrazione dei Prototipi al carico della libreria (costruzione di oggetti globali).

Sto scrivendo un server composto da un numero di librerie. Esiste un certo numero di librerie "comuni", quindi una libreria per servizio.Una biblioteca "principale" ha il compito di guardare il messaggio ricevuto e invocare il servizio giusto in base a un tasto ... Questo utilizza un semplice std::map.

L'utilizzo di un Singleton per la mappa mi consente di avere un codice completamente disaccoppiato. Nessuna libreria dipende dalla mia libreria di servizi, nessuna linea di codice al di fuori della mia biblioteca di servizi ha il compito di registrare il suo servizio. In effetti, è tale che posso decidere quali servizi sono incorporati semplicemente modificando il mio comando "link" in fase di compilazione: se non faccio collegamenti con una libreria, il suo servizio non è incorporato.

Ci trovo davvero utile lì ... per la configurazione e così preferisco usare il MonoPattern: ovvero una normale classe di ricerca con tutte le istanze che condividono gli stessi dati (quindi avvolgendo un vero singleton). Semplifica la migrazione nel caso in cui sia necessario poiché i clienti non sanno di utilizzare un sotto copertura Singleton.

1
  • Registrazione.

  • Ricerca di risorse stringa localizzate, ad es. Strings.get("CONFIRM_DELETE").

Entrambe queste cose non sono dettagli che dovrebbero essere esposti nell'interfaccia pubblica degli oggetti, quindi ha senso utilizzare un Singleton qui.

+1

Non sono d'accordo sul secondo, almeno in alcune applicazioni. Cosa succede se vuoi supportare più lingue contemporaneamente? –

+0

Cosa intendi subito? Strings.get ("pippo") recupererà la stringa corretta da un file di proprietà basato sulla lingua corrente. Cambia la lingua, riavvia il programma e ottieni le nuove stringhe di lingua. –

+1

Se si è un server di rete che gestisce connessioni da tutto il mondo, è possibile inviare stringhe a un client in una lingua e a un altro client in un'altra lingua. –

0

Oltre al logging (come molti altri hanno già menzionato), ho utilizzato singleton per contenitori Inversion of Control (IoC). Le dipendenze vengono registrate una volta all'inizio dell'applicazione e una può risolvere una dipendenza in qualsiasi momento durante l'applicazione utilizzando il metodo Singleton.

+0

È simile a ciò che è noto anche come pattern Locator del servizio o sto mescolando i miei pattern? :) – Grundlefleck

4

Ampliare il mio commento ...

la domanda è mal formulata, single sembrano funzionare bene in molte situazioni. Dovrebbe essere "quali sono alcune situazioni specifiche in cui i singleton non espongono le loro proprietà negative?" In breve, "quando le variabili globali sono buone"?

  1. Una variabile globale è una variabile globale.

    Non appena si utilizza

    void f() { X* x = X::getInstance(); ... }

    invece di void f(X*), l'ordine per il piatto di spaghetti è stata accettata.

  2. I singletons proliferano e preferiscono dipendere l'uno dall'altro. SessionManager utilizza EventManager che utilizza LogManager. Qualcuno vuole che i file di registro menzionino il nome dell'utente corrente. Il manutentore LogManager aggiunge SessionManager::getInstance()->getUser()->getName();, tutto rose fino al LoginManager, che utilizza anche LogManager, vuole registrare un errore di accesso.

  3. I singleton inibiscono la testabilità.

    La proprietà a istanza singola è semi-utile solo nel codice di produzione. Potrebbe non essere possibile testare la funzione void f() e probabilmente avrà (pochi) test solo per il percorso felice.

Come potete immaginare, la mia risposta a quando le variabili globali sono buone? è "mai". Che cos'è tuo?

+2

* "... quando le variabili globali sono buone?" * Mi stai chiedendo? Finora, userei i singleton (chiamali globali se vuoi) quando l'iniezione di dipendenza sarebbe una PITA totale (una PITA maggiore dei problemi che i globals ti danno con i test unitari). Ad esempio, non riesco a immaginare di passare un oggetto di registrazione ad ognuna delle mie classi. –

+0

-1 Per non aver risposto alla mia domanda, mi dispiace (non sono d'accordo con il tuo punto di vista, comunque). Volevo sapere quali sono ** le situazioni specifiche ** dove i singleton (chiamali globali se vuoi) funzionano bene. –

+0

ho difficoltà a credere che * ognuna delle tue classi * abbia qualche attività commerciale che registra le sue operazioni. a meno che non si usi la registrazione come sostituto di un debugger. comunque, nei casi in cui ho incontrato questa obiezione, il (percepito o reale) è stato indotto dal codice spaghetti. dopo il refactoring, i precedenti singleton sono stati superati laddove necessario, il che si è rivelato molto gestibile. –

1
  • Quando il dominio specifica che esiste una sola istanza unica di qualcosa che si sta modellando

credo ancora single dovrebbero essere evitati (in Java, almeno).

Ci sono due cose diverse da considerare: il concetto di e il meccanismo di di far rispettare il pattern Singleton.

Il concetto di Singletons ha molti usi, registrazione, configurazione, per non parlare quando il dominio su cui stai lavorando ha effettivamente cose in cui c'è sempre una sola istanza e desideri modellarlo. Cioè un'azienda ha un solo ufficio di elaborazione delle spese e l'invio di moduli di spesa a un ufficio non valido è sbagliato, l'ufficio è in realtà un singleton. Il concetto di un singleton ha molti usi legittimi.

Tuttavia, di solito è il meccanismo che causa il problema. In Java applichiamo un oggetto che non può essere costruito dichiarando il costruttore private, il problema con questo è che dobbiamo anche fornire un punto di accesso globale all'istanza attraverso la classe concreta. Questo collega tutto nella tua applicazione a quella classe concreta, che non può essere cambiata durante l'esecuzione o derisa nei test unitari. È questo meccanismo che è considerato malvagio, soprattutto in termini di testabilità.

Se il concetto di Singleton può essere separato dai meccanismi poveri, non sarebbe così male. Un esempio, posso pensare è l'ambito @Singleton disponibile in Guice. Nel contesto di Guice, garantisce un'istanza, ma non lo raggiunge con il malvagio costruttore privato/meccanismo di accesso globale.

2

Generazione di una sequenza di numeri casuali: il generatore casuale deve essere univoco, non istanziato per ciascun utilizzo. Si potrebbe voler implementare questo come un singleton a livello di thread; tuttavia, un singleton per l'intero processo è ancora appropriato in questo caso.

Problemi correlati