Cosa c’è di così male nei singleton?

Il modello singleton è un membro completamente retribuito del libro dei modelli di GoF , ma ultimamente sembra piuttosto orfano dal mondo degli sviluppatori. Uso ancora un bel po ‘di singleton, specialmente per le lezioni di fabbrica , e mentre devi essere un po’ attento ai problemi di multithreading (come ogni class in effetti), non riesco a capire perché sono così terribili.

Specialmente Overflow dello Stack sembra presumere che tutti siano d’accordo sul fatto che Singletons sia malvagio. Perché?

Supporta le tue risposte con ” fatti, riferimenti o competenze specifiche

Parafrasato da Brian Button:

  1. Sono generalmente usati come istanze globali, perché è così brutto? Perché nascondi le dipendenze della tua applicazione nel codice, invece di esporle attraverso le interfacce. Fare qualcosa di globale per evitare di passarlo è un odore di codice .

  2. Essi violano il principio della responsabilità unica : in virtù del fatto che controllano la propria creazione e il proprio ciclo di vita.

  3. Costoro intrinsecamente causano un accoppiamento stretto del codice. In molti casi ciò li rende falsi in fase di test.

  4. Portano lo stato in giro per tutta la vita dell’applicazione. Un altro successo per i test, dal momento che si può finire con una situazione in cui è necessario ordinare i test, che è un grande no no per i test unitari. Perché? Perché ogni test unitario dovrebbe essere indipendente dall’altro.

I single risolvono un problema (e uno solo).

Contesa di risorse.

Se hai qualche risorsa

( 1 ) può avere solo una singola istanza, e

( 2 ) devi gestire quella singola istanza,

hai bisogno di un singleton .

Non ci sono molti esempi Un file di registro è il più grande. Non vuoi semplicemente abbandonare un singolo file di registro. Vuoi svuotare, sincronizzare e chiudere correttamente. Questo è un esempio di una singola risorsa condivisa che deve essere gestita.

È raro che tu abbia bisogno di un singleton. Il motivo per cui sono cattivi è che si sentono come un globale e sono un membro del progetto GoF Design Patterns .

Quando pensi di aver bisogno di un globale, stai probabilmente commettendo un terribile errore di progettazione.

Alcuni snob di codice li guardano dall’alto come se fossero solo glorificati. Allo stesso modo in cui molte persone odiano la dichiarazione goto ci sono altri che odiano l’idea di usare sempre un globale . Ho visto diversi sviluppatori fare di tutto per evitare un globale perché hanno considerato l’utilizzo di uno come ammissione di fallimento. Strano ma vero.

In pratica il pattern Singleton è solo una tecnica di programmazione che è una parte utile del tuo kit di strumenti. Di volta in volta potresti scoprire che è la soluzione ideale e quindi usarla. Ma usarlo solo per vantarsi dell’uso di un modello di design è altrettanto stupido che rifiutarsi di usarlo perché è solo globale .

Misko Hevery, di Google, ha alcuni articoli interessanti proprio su questo argomento …

Singletons is Pathological Liars ha un esempio di test unitario che illustra come i singleton possono rendere difficile capire le catene di dipendenza e avviare o testare un’applicazione. È un esempio abbastanza estremo di abuso, ma il punto che egli fa è ancora valido:

I singleton non sono altro che uno stato globale. Lo stato globale lo rende in modo che i tuoi oggetti possano ottenere segretamente cose che non sono dichiarate nelle loro API e, di conseguenza, Singletons trasforma le tue API in bugiardi patologici.

Dove tutti i Singletons Gone fanno il punto che l’iniezione di dipendenza ha reso facile ottenere istanze a costruttori che li richiedono, il che allevia il bisogno di fondo dei cattivi Singleton globali decifrati nel primo articolo.

Penso che la confusione sia causata dal fatto che le persone non conoscono la reale applicazione del modello Singleton. Non posso sottolineare abbastanza questo. Singleton non è un modello per avvolgere i globali. Il modello Singleton deve essere utilizzato solo per garantire che una e una sola istanza di una determinata class esista durante il runtime.

La gente pensa che Singleton sia malvagio perché lo stanno usando per i globals. È a causa di questa confusione che Singleton è guardato dall’alto in basso. Per favore, non confondere Singletons e Globali. Se utilizzato per lo scopo per il quale è stato concepito, otterrete benefici estremi dal modello Singleton.

Una cosa piuttosto brutta dei singleton è che non è ansible estenderli molto facilmente. Fondamentalmente devi build un qualche tipo di decoratore o qualcosa del genere se vuoi cambiare il loro comportamento. Inoltre, se un giorno si desidera avere più modi di fare quella cosa, può essere piuttosto doloroso cambiare, a seconda di come si dispone il codice.

Una cosa da notare, se usi i singleton, prova a passarli a chiunque li abbia bisogno piuttosto che averli ad accedervi direttamente … Altrimenti se decidessi di avere più modi di fare la cosa che Singleton fa, sarà piuttosto difficile da cambiare poiché ogni class incorpora una dipendenza se accede direttamente al singleton.

Quindi in poche parole:

 public MyConstructor(Singleton singleton) { this.singleton = singleton; } 

piuttosto che:

 public MyConstructor() { this.singleton = Singleton.getInstance(); } 

Credo che questo tipo di schema sia chiamato iniezione di dipendenza ed è generalmente considerato una buona cosa.

Come ogni modello però … Pensaci e considera se il suo uso nella situazione data è inappropriato o no … Le regole sono fatte per essere rotte di solito, e gli schemi non dovrebbero essere applicati senza un pensiero.

Il modello singleton non è un problema in sé. Il problema è che il pattern è spesso usato da persone che sviluppano software con strumenti orientati agli oggetti senza avere una solida conoscenza dei concetti OO. Quando i singleton vengono introdotti in questo contesto tendono a crescere in classi ingestibili che contengono metodi di supporto per ogni piccolo uso.

I singleton sono anche un problema dal punto di vista dei test. Tendono a rendere difficili da scrivere i test unitari isolati. L’inversione del controllo (IoC) e l’ iniezione di dipendenza sono schemi pensati per superare questo problema in un modo orientato agli oggetti che si presta al collaudo di unità.

In un ambiente raccolto , i singleton possono diventare rapidamente un problema per quanto riguarda la gestione della memoria.

C’è anche lo scenario multi-thread in cui i singleton possono diventare un collo di bottiglia e un problema di sincronizzazione.

Un singleton viene implementato utilizzando un metodo statico. I metodi statici sono evitati da persone che eseguono test unitari perché non possono essere derisi o soppressi. La maggior parte delle persone su questo sito sono grandi sostenitori dei test unitari. La convenzione generalmente più accettata per evitarli sta usando l’ inversione del modello di controllo .

Anche i single sono cattivi quando si parla di clustering . Perché quindi, non hai più “esattamente un singleton” nella tua applicazione.

Si consideri la seguente situazione: come sviluppatore, è necessario creare un’applicazione Web che accede a un database. Per garantire che le chiamate simultanee al database non si mettano in conflitto tra loro, si crea un salvataggio SingletonDao thread-save:

 public class SingletonDao { // songleton's static variable and getInstance() method etc. omitted public void writeXYZ(...){ synchronized(...){ // some database writing operations... } } } 

Quindi sei sicuro che esiste un solo singleton nella tua applicazione e tutti i database passano attraverso questo solo SingletonDao . Il tuo ambiente di produzione ora si presenta così: Singleton Singolo

Tutto va bene finora.

Ora, considera di voler impostare più istanze della tua applicazione web in un cluster. Ora, improvvisamente hai qualcosa del genere:

Molti singleton

Sembra strano, ma ora hai molti singleton nella tua applicazione . E questo è esattamente ciò che non dovrebbe essere un singleton: avere molti oggetti in esso. Questo è particolarmente grave se tu, come mostrato in questo esempio, vuoi effettuare chiamate sincronizzate a un database.

Ovviamente questo è un esempio di cattivo utilizzo di un singleton. Ma il messaggio di questo esempio è: non si può contare sul fatto che esista esattamente un’istanza di un singleton nella propria applicazione, specialmente quando si parla di clustering.

  1. È facilmente (ab) usato come variabile globale.
  2. Le classi che dipendono dai singleton sono relativamente più difficili da testare separatamente.

Il monopolio è il diavolo e i singleton con stato non-readonly / mutable sono il problema ‘reale’ …

Dopo aver letto Singletons sono bugiardi patologici, come suggerito nella risposta di Jason, mi sono imbattuto in questo piccolo bocconcino che fornisce l’esempio migliore di come i singleton siano spesso abusati.

Globale è male perché:

  • un. Causa conflitto nello spazio dei nomi
  • b. Espone lo stato in modo ingiustificato

Quando si tratta di Singletons

  • un. Il modo OO esplicito di chiamarli, previene i conflitti, quindi indica a. non è un problema
  • b. I singleton senza stato sono (come le fabbriche) non sono un problema. I single con stato possono di nuovo cadere in due categorie, quelli che sono immutabili o scrivono una volta e leggono molti (file di configurazione / proprietà). Questi non sono male. Singletons mutevoli, che sono i portatori di riferimento sono quelli di cui stai parlando.

Nell’ultima affermazione si riferisce al concetto del blog di ‘singletons are liars’.

Come si applica a Monopoly?

Per iniziare una partita di monopolio, prima:

  • stabiliamo le regole prima in modo che tutti siano sulla stessa pagina
  • All’inizio del gioco tutti hanno una partenza uguale
  • viene presentato un solo insieme di regole per evitare confusione
  • le regole non possono cambiare durante il gioco

Ora, per tutti quelli che non hanno mai giocato a livello monopolistico, questi standard sono ideali nel migliore dei casi. Una sconfitta in monopolio è difficile da inghiottire perché, il monopolio riguarda i soldi, se perdi devi guardare diligentemente il resto dei giocatori a terminare il gioco, e le perdite sono solitamente rapide e schiaccianti. Di conseguenza, le regole di solito vengono distorte a un certo punto per servire l’interesse personale di alcuni dei giocatori a scapito degli altri.

Quindi stai giocando al monopolio con gli amici Bob, Joe e Ed. Stai rapidamente costruendo il tuo impero e consumando quote di mercato ad un tasso esponenziale. I tuoi avversari si stanno indebolendo e inizi ad annusare il sangue (in senso figurato). Il tuo amico Bob ha messo tutti i suoi soldi in un sistema di blocco per bloccare il maggior numero ansible di proprietà di basso valore, ma il suo non sta ricevendo un alto ritorno sugli investimenti nel modo in cui si aspettava. Bob, come un colpo di sfortuna, atterra sul tuo Boardwalk e viene eliminato dal gioco.

Ora il gioco passa dal lancio amichevole dei dadi a un business serio. Bob è stato reso l’esempio del fallimento e Joe e Ed non vogliono finire come “quel tipo”. Quindi, essendo il giocatore principale tu, all’improvviso, diventi il ​​nemico. Joe e Ed iniziano a praticare i mestieri sottobanco, le iniezioni di denaro dietro le quinte, lo scambio di casa sottovalutato e in generale qualsiasi cosa che ti indebolisca come giocatore finché uno di loro non sale in alto.

Quindi, invece di vincere uno di loro, il processo inizia dappertutto. All’improvviso, un insieme finito di regole diventa un bersaglio mobile e il gioco degenera nel tipo di interazioni sociali che costituirebbero le fondamenta di ogni reality show televisivo di alto livello sin dai tempi di Survivor. Perché, perché le regole stanno cambiando e non c’è consenso su come / perché / cosa dovrebbero rappresentare e, cosa più importante, non c’è una sola persona che prende le decisioni. Ogni giocatore nel gioco, a quel punto, sta facendo le proprie regole e il caos si verifica fino a quando due giocatori sono troppo stanchi per mantenere la sciarada e lentamente arrendersi.

Quindi, se un regolamento per un gioco rappresentasse accuratamente un singleton, il regolamento di monopolio sarebbe un esempio di abuso.

Come si applica alla programmazione?

A parte tutti gli ovvi problemi di sicurezza e sincronizzazione dei thread che i singleton mutabili presentano … Se si dispone di un set di dati, che è in grado di essere letto / manipolato da più origini diverse contemporaneamente ed esiste durante la vita dell’esecuzione dell’applicazione, è probabilmente un buon momento per fare un passo indietro e chiedere “sto usando il giusto tipo di struttura dati qui”.

Personalmente, ho visto un programmatore abusare di un singleton usandolo come una sorta di archivio di database cross-thread contorto all’interno di un’applicazione. Avendo lavorato direttamente sul codice, posso attestare che è stato lento (a causa di tutti i blocchi di thread necessari per renderlo thread-safe) e un incubo su cui lavorare (a causa della natura imprevedibile / intermittente dei bug di sincronizzazione), e quasi imansible da testare in condizioni di “produzione”. Certo, un sistema potrebbe essere stato sviluppato utilizzando il polling / signaling per superare alcuni dei problemi di prestazioni ma che non risolverebbe i problemi con i test e, perché preoccuparsi quando un database “reale” può già realizzare la stessa funzionalità in un ambiente molto più robusto / modo scalabile.

Un Singleton è solo un’opzione se hai bisogno di ciò che un singleton fornisce. Un’istanza di sola lettura di scrittura di un object. Quella stessa regola dovrebbe sovrapporsi anche alle proprietà / ai membri dell’object.

Singleton non riguarda la singola istanza!

A differenza di altre risposte, non voglio parlare di ciò che è sbagliato in Singletons, ma per mostrarti quanto sono potenti e fantastici quando vengono usati correttamente!

  • Problema : Singleton può rappresentare una sfida nell’ambiente multi-threading
    Soluzione : utilizzare un processo di bootstrap con thread singolo per inizializzare tutte le dipendenze del singleton.
  • Problema : è difficile deridere i singleton.
    Soluzione : utilizzare il metodo Modello di fabbrica per la derisione
    MyModel myModel = Factory.inject(MyModel.class); È ansible associare MyModel alla class TestMyModel che lo eredita, ovunque venga iniettato TestMyModel si otterrà l’ TestMyModel TestMyModel.
  • Problema : i singleton possono causare porri di memoria non eliminati.
    Soluzione : bene, disponili! Implementa un callback nella tua app per disporre correttamente di un singletons, dovresti rimuovere tutti i dati ad essi collegati e infine: rimuoverli dalla Factory.

Come ho dichiarato al titolo Singleton non riguardano la singola istanza.

  • I singleton migliorano la leggibilità : puoi guardare la tua class e vedere quale singleton ha iniettato per capire quali sono le sue dipendenze.
  • Singletons migliora la manutenzione : una volta rimossa una dipendenza da una class che hai appena eliminato qualche iniezione singleton, non devi modificare un grosso link di altre classi che hanno semplicemente spostato la tua dipendenza (questo è un codice maleodorante per me @Jim Burger )
  • Singletons migliora la memoria e le prestazioni : quando succede qualcosa nella tua applicazione, e richiede una lunga catena di callback da consegnare, stai sprecando memoria e prestazioni, usando Singleton stai tagliando il middle man e migliorando le prestazioni e l’utilizzo della memoria ( evitando allocazioni di variabili locali non necessarie).

La mia risposta su come i singleton sono cattivi è sempre “sono difficili da fare bene”. Molti dei componenti fondamentali delle lingue sono singleton (classi, funzioni, spazi dei nomi e persino operatori), così come le componenti in altri aspetti dell’informatica (localhost, route predefinita, filesystem virtuale, ecc.) E non è un caso. Mentre causano problemi e frustrazioni di tanto in tanto, possono anche fare un sacco di cose che funzionano MOLTO meglio.

I due più grandi fallimenti che vedo sono: considerarli globali e non riuscire a definire la chiusura di Singleton.

Tutti parlano di Singleton come globali, perché in pratica lo sono. Tuttavia, molto (purtroppo, non tutti) della cattiveria in un contesto globale non deriva intrinsecamente dall’essere globale, ma dal modo in cui lo si usa. Lo stesso vale per Singletons. In realtà più che “istanza singola” non ha realmente bisogno di “accessibile globalmente”. È più un sottoprodotto naturale, e dato tutto il male che sappiamo proviene da esso, non dovremmo avere tanta fretta per sfruttare l’accessibilità globale. Una volta che i programmatori vedono un Singleton sembrano sempre accedervi direttamente attraverso il suo metodo di istanza. Invece, dovresti navigare ad esso come faresti con qualsiasi altro object. La maggior parte del codice non dovrebbe nemmeno sapere che si tratta di un Singleton (accoppiamento lento, giusto?). Se solo un piccolo pezzetto di codice accede all’object come se fosse globale, molti danni vengono annullati. Raccomando di applicarlo limitando l’accesso alla funzione di istanza.

Anche il contesto di Singleton è molto importante. La caratteristica che definisce un Singleton è che c’è “solo uno”, ma la verità è che è “solo uno” all’interno di un qualche tipo di contesto / spazio dei nomi. Di solito sono uno: uno per thread, processo, indirizzo IP o cluster, ma possono anche essere uno per processore, macchina, spazio dei nomi / caricatore di class / qualsiasi, subnet, Internet, ecc.

L’altro, meno comune, è l’errore di ignorare lo stile di vita di Singleton. Solo perché ce n’è uno solo non significa che un Singleton è un onnipotente “sempre era e sempre sarà”, né è generalmente desiderabile (gli oggetti senza inizio e fine violano ogni tipo di ipotesi utili nel codice, e dovrebbero essere impiegati solo nella più disperata delle circostanze.

Se si evitano quegli errori, Singletons può ancora essere un PITA, ma è pronto a vedere che molti dei problemi peggiori sono significativamente mitigati. Immagina un Java Singleton, che è definito esplicitamente come una volta per classloader (il che significa che ha bisogno di un criterio di sicurezza del thread), con metodi di creazione e distruzione definiti e un ciclo di vita che determina quando e come vengono richiamati e il cui metodo “istanza” ha protezione del pacchetto in modo che sia generalmente accessibile tramite altri oggetti non globali. Ancora una potenziale fonte di problemi, ma certamente molto meno problemi.

Tristemente, piuttosto che insegnare buoni esempi di come fare Singletons. Insegniamo cattivi esempi, lasciamo che i programmatori li usino per un po ‘e poi diciamo loro che sono un cattivo modello di progettazione.

Vedi Wikipedia Singleton_pattern

È anche considerato un anti-modello da alcune persone, che ritengono che sia eccessivamente utilizzato, introducendo limitazioni inutili in situazioni in cui non è effettivamente richiesta una sola istanza di una class. [1] [2] [3] [4]

Riferimenti (solo riferimenti pertinenti all’articolo)

  1. ^ Alex Miller. Modelli che odio # 1: Singleton , luglio 2007
  2. ^ Scott Densmore. Perché i singleton sono cattivi , maggio 2004
  3. ^ Steve Yegge. Singletons considerati stupidi , settembre 2004
  4. ^ JB Rainsberger, IBM. Usa saggiamente i tuoi singleton , luglio 2001

Non è che gli stessi singleton siano cattivi, ma lo schema di progettazione di GoF è. L’unica vera argomentazione valida è che il modello di progettazione GoF non si presta a testare, specialmente se i test vengono eseguiti in parallelo.

L’utilizzo di una singola istanza di una class è un costrutto valido se si applicano i seguenti mezzi nel codice:

  1. Assicurati che la class che verrà utilizzata come singleton implementa un’interfaccia. Ciò consente di implementare stub o mock utilizzando la stessa interfaccia

  2. Assicurati che Singleton sia sicuro per i thread. Questo è un dato.

  3. Il singleton dovrebbe essere di natura semplice e non eccessivamente complicato.

  4. Durante il runtime dell’applicazione, in cui i singleton devono essere passati a un determinato object, utilizzare un class factory che costruisce quell’object e fare in modo che la class factory passi l’istanza singleton alla class che ne ha bisogno.

  5. Durante i test e per garantire un comportamento deterministico, creare la class singleton come istanza separata della class stessa o di uno stub / mock che implementa il proprio comportamento e passarlo come è nella class che lo richiede. Non utilizzare il fattore di class che crea quell’object sotto test che ha bisogno del singleton durante il test, poiché passerà la singola istanza globale di esso, che vanifica lo scopo.

Abbiamo utilizzato Singletons nelle nostre soluzioni con un grande successo che sono testabili garantendo un comportamento deterministico nei flussi di esecuzione paralleli.

Vince Huston ha questi criteri, che mi sembrano ragionevoli:

Singleton dovrebbe essere considerato solo se tutti e tre i seguenti criteri sono soddisfatti:

  • La proprietà della singola istanza non può essere ragionevolmente assegnata
  • L’inizializzazione pigra è desiderabile
  • L’accesso globale non è altrimenti previsto

Se la proprietà della singola istanza, quando e come si verifica l’inizializzazione e l’accesso globale non sono problemi, Singleton non è sufficientemente interessante.

Vorrei affrontare i 4 punti nella risposta accettata, si spera che qualcuno possa spiegare perché mi sbaglio.

  1. Perché le dipendenze nel codice sono nascoste? Esistono già dozzine di dipendenze nascoste (chiamate runtime C, chiamate API OS, chiamate di funzioni globali) e le dipendenze di singleton sono facili da trovare (cercare instance ()).

    “Fare qualcosa di globale per evitare di passarlo è un odore di codice.” Perché non passa qualcosa in giro per evitare di renderlo un singleton un odore di codice?

    Se stai passando un object attraverso 10 funzioni in una pila di chiamate solo per evitare un singleton, è così bello?

  2. Principio della singola responsabilità: penso che questo sia un po ‘vago e dipende dalla vostra definizione di responsabilità. Una domanda rilevante sarebbe, perché aggiungere questa specifica “responsabilità” a una questione di class?

  3. Perché passare un object ad una class lo rende più strettamente accoppiato che usare quell’object come un singleton all’interno della class?

  4. Perché cambia quanto dura lo stato? I single possono essere creati o distrutti manualmente, quindi il controllo è ancora lì e puoi rendere la vita uguale a quella di un object non singolo.

Per quanto riguarda i test unitari:

  • non tutte le classi devono essere testate da unità
  • non tutte le classi che devono essere testate su unità devono modificare l’implementazione del singleton
  • se hanno bisogno di essere testati unitamente e hanno bisogno di cambiare l’implementazione, è facile cambiare una class dall’uso di un singleton per far passare il singleton tramite l’iniezione di dipendenza.

Non ho intenzione di commentare l’argomento buono / cattivo, ma non li ho usati da quando è arrivata la spring . L’utilizzo dell’iniezione di dipendenza ha praticamente rimosso i miei requisiti per singleton, servicelocators e factory. Trovo che questo sia un ambiente molto più produttivo e pulito, almeno per il tipo di lavoro che faccio (applicazioni web basate su Java).

I singleton sono cattivi da un punto di vista purista.

Da un punto di vista pratico, un singleton è un trade-off in via di sviluppo rispetto alla complessità .

Se sai che la tua applicazione non cambierà più di tanto, sono piuttosto giusti. Sappi solo che potrebbe essere necessario rifattorizzare le cose se le tue esigenze cambiano in modo inaspettato (il che è abbastanza OK nella maggior parte dei casi).

Singletons a volte complicano anche i test unitari .

There is nothing inherently wrong with the pattern, assuming it is being used for some aspect of your model which is truly single.

I believe the backlash is due to its overuse which, in turn, is due to the fact that it’s the easiest pattern to understand and implement.

Singleton is a pattern and can be used or abused just like any other tool.

The bad part of a singleton is generally the user (or should I say the inappropriate use of a singleton for things it is not designed to do). The biggest offender is using a singleton as a fake global variable.

When you write code using singletons, say, a logger or a database connection, and afterwards you discover you need more than one log or more than one database, you’re in trouble.

Singletons make it very hard to move from them to regular objects.

Also, it’s too easy to write a non-thread-safe singleton.

Rather than using singletons, you should pass all the needed utility objects from function to function. That can be simplified if you wrap all them into a helper object, like this:

 void some_class::some_function(parameters, service_provider& srv) { srv.get().log("Hi there!"); this->another_function(some_other_parameters, srv); } 

The problems with singletons is the issue of increased scope and therefore coupling . There is no denying that there are some of situations where you do need access to a single instance, and it can be accomplished other ways.

I now prefer to design around an inversion of control (IoC) container and allow the the lifetimes to be controlled by the container. This gives you the benefit of the classs that depend on the instance to be unaware of the fact that there is a single instance. The lifetime of the singleton can be changed in the future. Once such example I encountered recently was an easy adjustment from single threaded to multi-threaded.

FWIW, if it a PIA when you try to unit test it then it’s going to PIA when you try to debug, bug fix or enhance it.

Recent article on this subject by Chris Reath at Coding Without Comments .

Note: Coding Without Comments is no longer valid. However, The article being linked to has been cloned by another user.

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx

Here is one more thing about singletons which nobody said yet.

In most cases “singletonity” is a detail of implementation for some class rather than characteristic of its interface. Inversion of Control Container may hide this characteristic from class users; you just need to mark your class as a singleton (with @Singleton annotation in Java for example) and that’s it; IoCC will do the rest. You don’t need to provide global access to your singleton instance because the access is already managed by IoCC. Thus there is nothing wrong with IoC Singletons.

GoF Singletons in opposite to IoC Singletons are supposed to expose “singletonity” in the interface through getInstance() method, and so that they suffer from everything said above.

Singletons are NOT bad. It’s only bad when you make something globally unique that isn’t globally unique.

However, there are “application scope services” (think about a messaging system that makes components interact) – this CALLS for a singleton, a “MessageQueue” – class that has a method “SendMessage(…)”.

You can then do the following from all over the place:

MessageQueue.Current.SendMessage(new MailArrivedMessage(…));

And, of course, do:

MessageQueue.Current.RegisterReceiver(this);

in classs that implement IMessageReceiver.

Too many people put objects which are not thread safe in a singleton pattern. I’ve seen examples of a DataContext ( LINQ to SQL ) done in a singleton pattern, despite the fact that the DataContext is not thread safe and is purely a unit-of-work object.

Because they are basically object oriented global variables, you can usually design your classs in such a way so that you don’t need them.

A pattern emerges when several people (or teams) arrives at similar or identical solutions. A lot of people still use singletons in their original form or using factory templates (good discussion in Alexandrescu’s Modern C++ Design). Concurrency and difficulty in managing the lifetime of the object are the main obstacles, with the formsr easily managed as you suggest.

Like all choices, Singleton has its fair share of ups and downs. I think they can be used in moderation, especially for objects that survive the application life span. The fact that they resemble (and probably are) globals have presumably set off the purists.

Firstly a class and its collaborators should firstly perform their intended purpose rather than focusing on deoendents. Lifecycle management (when instances are creared snd when they go out of scope) should not be part of the cladses responsibility. The accepted best practice for this is to craft or configure a new component to manage dependencies using dependency injection.

Often software gets more complicated it makes sense to have multiple independent instances of the “singleton” class with different state. Committing code to simply grab the singleton is wrong in such cases. Using Singleton.getInstance() might be ok for small simple systems but it doesn’t work / scale when one might need a different instance of the same class.

No class should be thought of as a singleton but rather that should be an aplication of it’s usage or how it is used to configure dependents. For a quick and nasty this does not matter- just luke hardcoding say file paths does not matter but for bigger applications such dependencies need to be factored out and managed in more appropriate way using DI.

The problems that singleton cause in testing is a symptom of their hard coded single usage case/environment. The test suite and the many tests are each individual and separate something that is not compatible with hardcoding a singleton.