Perché usare un singleton invece di metodi statici?


93

Non ho mai trovato buone risposte a queste semplici domande sulle classi di aiuto / utilità:

Perché dovrei creare un singleton (senza stato) invece di utilizzare metodi statici?

Perché dovrebbe essere necessaria un'istanza di oggetto se un oggetto non ha uno stato?



Non pensare dato che parliamo di 2 lingue diverse quindi la risposta potrebbe variare, ma grazie per il link, in java non si è mai sentito il termine "monostate"
Sebastien Lorber

Risposte:


79

Spesso, i singleton vengono utilizzati per introdurre una sorta di stato globale in un'applicazione. (Più spesso del necessario, ad essere onesti, ma questo è un argomento per un'altra volta.)

Tuttavia, ci sono alcuni casi d'angolo in cui anche un singleton senza stato può essere utile:

  • Ti aspetti di estenderlo con lo stato nel prossimo futuro.
  • Hai bisogno di un'istanza di oggetto per qualche motivo tecnico particolare .
    Esempio: oggetti di sincronizzazione per l' istruzione C # locko Java synchronized.
  • Hai bisogno dell'ereditarietà, cioè vuoi essere in grado di sostituire facilmente il tuo singleton con un altro usando la stessa interfaccia ma un'implementazione diversa.
    Esempio: il Toolkit.getDefaultToolkit()metodo in Java restituirà un singleton il cui tipo esatto dipende dal sistema.
  • Vuoi l' uguaglianza dei riferimenti per un valore sentinella .
    Esempio: DBNull.Valuein C #.

27
Vado con +1, anche se i singleton IMHO sono abusati per introdurre stati globali. Lo scopo di un singleton non è rendere un oggetto globalmente disponibile, ma imporre che un oggetto venga istanziato solo una volta. Gli oggetti globali sono un male necessario. A meno che non sia realmente richiesto, si dovrebbe cercare di non usarli, poiché generalmente portano a un accoppiamento elevato, con SomeSingleton.getInstance (). SomeMethod () ovunque. :)
back2dos

Può essere utile nei giochi in cui si desidera una sola istanza di rendering invece di più istanze di rendering, o con una classe di piping di rete in cui si configura un canale sicuro che può essere solo una connessione alla volta.
Tschallacka

2
"Sostituisci facilmente il tuo singleton" è il punto più importante dal mio punto di vista. Il resto è abbastanza vicino all'implementazione di una classe statica.
Teoman shipahi

1
I singleton sono valori sentinella non null utili per i tipi di somma / prodotto e simili. Ad esempio, essendo il valore Nessuno / Niente in un tipo di opzione o il valore Vuoto per un tipo di raccolta. Ottieni test veloci Nessuno / Vuoto come bonus, perché l'uguaglianza dei riferimenti è tutto ciò che serve.
itsbruce

@itsbruce: i tuoi esempi non sono singoli : l'elenco vuoto non è l'unica istanza possibile della classe List e il valore None non è l'unica istanza possibile della classe Option. Tuttavia, ci sono esempi in cui il valore sentinella sono singoli e mi sono preso la libertà di aggiungerne uno alla mia risposta. Grazie per l'input!
Heinzi

37

Ho potuto vedere un caso per un singleton senza stato utilizzato al posto di una classe di metodi statici, vale a dire per Dependency Injection .

Se hai una classe helper di funzioni di utilità che stai usando direttamente, crea una dipendenza nascosta; non hai il controllo su chi può usarlo o dove. L'iniezione della stessa classe helper tramite un'istanza singleton senza stato consente di controllare dove e come viene utilizzata e di sostituirla / deriderla / ecc. Quando necessario.

Rendendolo un'istanza singleton garantisce semplicemente che non stai allocando più oggetti del tipo del necessario (dal momento che ne hai bisogno solo uno).


1
"non hai alcun controllo su chi può usarlo o dove." Perché qualcuno dovrebbe averne bisogno?
hagrawal

1
@hagrawal a scopo di test, dovresti essere in grado di prenderlo in giro
Jemshit Iskenderov

15

In realtà ho trovato un'altra risposta non menzionata qui: i metodi statici sono più difficili da testare.

Sembra che la maggior parte dei framework di test funzioni alla grande per deridere i metodi di istanza, ma molti di loro non gestiscono in modo decente il mock dei metodi statici.


2
Ma Powermock sembra essere in grado di farlo
Sebastien Lorber

6

Nella maggior parte dei linguaggi di programmazione le classi sfuggono molto al sistema di tipi. Sebbene una classe, con i suoi metodi statici e le sue variabili, sia un oggetto, molto spesso non può implementare un'interfaccia o estendere altre classi. Per questo motivo, non può essere utilizzato in modo polimorfico, poiché non può essere il sottotipo di un altro tipo. Ad esempio, se si dispone di un'interfaccia IFooablerichiesta da diverse firme di metodi di altre classi, l'oggetto classe StaticFoonon può essere utilizzato al posto di IFooable, mentre FooSingleton.getInstance()può (supponendo, FooSingletonimplementa IFooable).

Si noti che, come ho commentato la risposta di Heinzi, un singleton è uno schema per controllare l'istanza. Sostituisce new Class()con Class.getInstance(), che dà all'autore un Classmaggiore controllo sulle istanze, che può usare per prevenire la creazione di istanze inutili. Il singleton è solo un caso molto speciale del pattern factory e dovrebbe essere trattato come tale. L'uso comune lo rende piuttosto il caso speciale dei registri globali, che spesso finisce male, perché i registri globali non dovrebbero essere usati solo volenti o nolenti.

Se si prevede di fornire funzioni di supporto globali, i metodi statici funzioneranno perfettamente. La classe non agirà come classe, ma solo come spazio dei nomi. Suggerisco di preservare un'elevata coesione o potresti finire con problemi di accoppiamento più strani.

Greetz
back2dos


4

C'è un compromesso tra l'utilizzo di quale. I single possono o meno avere uno stato e si riferiscono a oggetti. Se non mantengono lo stato e vengono utilizzati solo per l'accesso globale, lo statico è migliore poiché questi metodi saranno più veloci. Ma se vuoi utilizzare oggetti e concetti OOP (polimorfismo dell'ereditarietà), allora il singleton è meglio.

Considera un esempio: java.lang.Runtime è una classe singleton in java. Questa classe consente diverse implementazioni per ogni JVM. L'implementazione è singola per JVM. Se questa classe fosse statica, non possiamo passare implementazioni diverse basate su JVM.

Ho trovato questo collegamento davvero utile: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

Spero che sia d'aiuto!!


Questa risposta è utile per includere un esempio concreto nel mondo reale.
systemovich

2

Per me "Want Object State usa Singleton, Want Function usa metodo statico"

Dipende da cosa vuoi. Ogni volta che si desidera lo stato dell'oggetto (ad es. Polimorfismo come stato Null invece di null, o stato predefinito), singleton è la scelta appropriata per te, mentre il metodo statico usa quando hai bisogno di una funzione (ricevi input e poi restituisci un output).

Consiglio per il caso singleton, dovrebbe essere sempre lo stesso stato dopo che è stato istanziato. Non dovrebbe essere clonabile, né ricevere alcun valore da impostare (eccetto la configurazione statica dal file, ad esempio il file delle proprietà in java).

PS Le prestazioni tra questi 2 sono diverse in millisecondi, quindi concentrati prima sull'architettura .


1

Singleton non è apolide, detiene lo stato globale.

Alcuni motivi che posso pensare di usare Singleton sono:

  • Per evitare perdite di memoria
  • Per fornire lo stesso stato a tutti i moduli in un'applicazione, ad es. Connessione al database

Lo so, ma in realtà un singleton può essere più o meno apolide ... Se non condivide alcun attributo di classe ...
Sebastien Lorber
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.