Domanda Cosa c'è di così male nei singleton? [chiuso]


Il modello singleton è un membro pienamente pagato del GoF'S libro dei modelli, ma ultimamente sembra piuttosto orfano dal mondo degli sviluppatori. Uso ancora un sacco di singleton, soprattutto per classi di fabbricae anche se devi stare un po 'attento ai problemi del multithreading (come ogni classe 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"


1737


origine


risposte:


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 è a odore di codice.

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

  3. Costoro intrinsecamente causano strettamente il codice accoppiato. 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.


1148



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,

avete 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. La ragione per cui sono cattivi è che si sentono come a globale e sono un membro completamente retribuito del GoF Modelli di progettazione libro.

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


399



Alcuni snob di codice li guardano dall'alto come se fossero solo glorificati. Nello stesso modo in cui molte persone odiano il vai a affermazione ci sono altri che odiano l'idea di usare mai a globale. Ho visto diversi sviluppatori andare a lunghezze straordinarie per evitare un globale perché hanno considerato l'utilizzo di uno come ammissione di fallimento. Strano ma vero.

In pratica il Singleton pattern è 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 così puoi vantarti di usare un design pattern è altrettanto stupido che rifiutarsi di usarlo mai perché è solo un globale.


306



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

Singletons sono bugiardi patologici ha un esempio di test unitario che illustra come i singleton possono rendere difficile la determinazione delle 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 sono finiti tutti i singleton fa notare che l'iniezione di dipendenza ha reso facile ottenere istanze a costruttori che li richiedono, il che allevia la necessità di fondo dei cattivi Singleton globali decifrati nel primo articolo.


200



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 globals. Il modello Singleton dovrebbe essere usato solo per garantire questo una e una sola istanza di una data classe esiste durante il tempo di esecuzione.

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.


103



Una cosa piuttosto brutta dei singleton è che non è possibile estenderli molto facilmente. Fondamentalmente devi costruire un qualche tipo di modello 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 classe 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 modelli non dovrebbe essere applicato volenti o nolenti senza pensarci


71



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. Inversione di controllo (IoC) e iniezione di dipendenza sono modelli pensati per superare questo problema in un modo orientato agli oggetti che si presta a test unitari.

In un raccolta dei rifiuti i singleton ambientali 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.


65



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 il inversione di controllo modello.


52



Anche i single sono cattivi quando si tratta di il 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 siano in conflitto tra loro, si crea un salvataggio del thread SingletonDao:

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 e solo SingletonDao. Il tuo ambiente di produzione ora si presenta così: Single Singleton

Tutto va bene finora.

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

Many singletons

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.


42



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

34