2012-07-02 11 views

risposta

47

Testing

Un motivo è che single non sono facili da maneggiare con test di unità. Non è possibile controllare l'istanziazione e per la loro stessa natura può mantenere lo stato tra le invocazioni.

Per questo motivo il principio di dependency injection è popolare. Ogni classe viene iniettata (configurata) con le classi che devono funzionare (piuttosto che derivare tramite accessori singleton) e quindi i test possono controllare quali istanze di classe dipendente utilizzare (e fornire mock se necessario).

Framework come Spring controllano il ciclo di vita dei loro oggetti e spesso creano singleton, ma questi oggetti vengono iniettati dai loro oggetti dipendenti dal framework. Pertanto, il codebase stesso non tratta gli oggetti come singleton.

ad es. piuttosto che questo (per esempio)

public class Portfolio { 
    private Calculator calc = Calculator.getCalculator(); 
} 

si dovrebbe iniettare la calcolatrice:

public class Portfolio { 
    public Portfolio(Calculator c) { 
     this.calc = c; 
    } 
} 

Così l'oggetto Portfolio Non sa/cura su come esistono molte istanze del Calculator. I test possono iniettare un dummy Calculator che rende facile il test.

Concurrency

Limitando a voi stessi di un'istanza di un oggetto, le opzioni per filettare sono limitati. L'accesso all'oggetto singleton può dover essere sorvegliato (ad esempio tramite sincronizzazione). Se è possibile mantenere più istanze di tali oggetti, è possibile adattare il numero di istanze ai thread in esecuzione e aumentare le capacità simultanee della base di codice.

+2

Quindi, come fanno le persone che usano i singleton a "Testare" e " "Concurrency"? – Pacerier

+0

Con qualche difficoltà. Strumenti come PowerMock possono fornire metodi per sovrascrivere i metodi singleton, ma sono strumenti complessi che fanno ricorso alla manipolazione bytecode –

21

La mia opinione personale è che viola il principio della responsabilità unica. Gli oggetti Singleton sono responsabili sia del loro scopo sia del controllo del numero di istanze prodotte che penso sia sbagliato.

Questo è il motivo per cui molte persone delegano il controllo a un oggetto di fabbrica.

+0

Penso che ciò renda sospetto [l'interpretazione di] SRP. –

+0

In che modo sospetti? – MikePatel

+0

Sospettoso in quanto ciò chiaramente non è una cosa che non va nei Singletons, ma l'interpretazione di SRP indica che lo è. SRP (o questa interpretazione di esso) sembrerebbe essere il colpevole. –

6

Ci sono molti requisiti che si potrebbe avere sul Singleton:

  1. inizializzazione differita;
  2. smaltimento adeguato;
  3. ambito (uno per thread, ad esempio).

In genere, anche, avrete un sacco di single nella vostra app, e il Singleton modello non consente codice riutilizzabile. Quindi, se vuoi attuare tutte queste preoccupazioni per tutti i tuoi singleton, vedrai immediatamente la sua qualità anti-pattern.

7

I singleton come tali non sono necessariamente un anti-pattern, ma hanno solo pochi vantaggi e diventano un antipattern quando vengono utilizzati in modo errato (cosa che accade spesso).

Spesso, i singleton non sono affatto singleton, ma "variabili globali mascherate". Inoltre, spesso vengono utilizzati quando la proprietà "solo una istanza" non è in realtà un vantaggio. (che di nuovo è bilanciato dal fatto che molte volte l'implementazione è sbagliata allo stesso tempo).

In aggiunta a ciò, possono essere difficili da implementare con il multithreading in mente (spesso fatto in modo errato o inefficiente) e perdono la maggior parte dei loro benefici se si desidera controllare la loro istanziazione.

Se si desidera avere il controllo dell'istanziazione, è necessario farlo manualmente a un certo punto all'inizio del programma, ma si potrebbe anche semplicemente creare un'istanza di un oggetto normale e inoltrarla in seguito.
Se l'ordine di distruzione è di qualche preoccupazione, è necessario implementarlo manualmente. Un singolo oggetto automatico nella funzione principale è tanto più semplice e pulito.

10

[Mutevole] Singleton è un anti-pattern di un anti-pattern.

Il significativo anti-pattern sottostante è lo stato globale (o stato dell'ambiente). Con lo stato globale hai un grande blog di dipendenza attraverso il tuo programma. Ciò influisce sul testing, ma questa è solo una parte delle conseguenze di una cattiva programmazione.

Stratificato su questo, Singleton aggiunge un livello di complessità completamente superfluo semplicemente dichiarando i campi modificabili static.

+2

i campi soffrono dello stesso esatto problema, è lo stato globale. Non riesco a vedere come usare i campi statici sia meglio di un singleton. Qualche informazione a riguardo? –

+2

@JuanMendes Come ho già detto, le statiche mutevoli sono meglio della statica mutabile singleton perché non hanno la complessità inutile. –

+0

Dovrei rivedere le risposte meglio prima di lasciare un commento. Il 100% è d'accordo con te. È fondamentalmente un eufemismo per lo stato globale, quindi chiamarlo come campi statici almeno non tenta di abbellirlo. –

3

Strano. Sembra che l'implementazione errata di un Singleton sia un "anti-pattern", non lo stesso Singleton.

Penso che abbiamo dimenticato che ogni programma deve iniziare da qualche parte. Deve esserci un'implementazione concreta di ogni astrazione, e alla fine ogni dipendenza sarà risolta, o la tua app non sarebbe molto utile.

La maggior parte dei framework DI consente di creare un'istanza di una classe come Singleton, la gestisce solo per te. Se si sceglie di fare da soli, l'iniezione di un singleton non è un problema. Anche Singleton IS è testabile e, se stai usando DI per iniettarlo, non rende instabile una classe.

IMO, come ogni altro modello là fuori (compresi DI e IoC) è uno strumento. A volte si adatta, a volte no.

Problemi correlati