The Singleton Pattern [duplicato]

26

Sono un nuovo programmatore (4 mesi nel mio primo lavoro) e recentemente mi sono interessato ai modelli di design. Uno che ho usato di recente è il Singleton. Tuttavia, guardando alcuni commenti su questo thread . Ha qualche feedback negativo; qualcuno può spiegare perché?

L'ho trovato utile in alcuni punti, ma probabilmente avrei potuto ottenere lo stesso senza usare una classe statica.

    
posta Darren Young 16.01.2011 - 19:21
fonte

7 risposte

27

Ha gli stessi problemi di una variabile globale.

It gives you global accesses to mutable state.

Qualunque cosa utilizzi Singleton ora è strettamente associata ad esso.

Try and avoid tight coupling. It makes the code hard to update. Hard to test.

Se la tua scelta è una variabile Singleton o globale. Di almeno Singleton fornisce l'inizializzazione pigra.

Di solito è meglio evitare lo stato mutabile accessibile a livello globale e passare tutta la dipendenza dal codice tramite parametri o nel costruttore. Questo disaccoppia il tuo codice da istanze specifiche.

Nota: l'accesso globale allo stato costante non è un grosso problema.

Ecco un bel discorso sull'argomento svolto da Google Engineers:
link

Singleton pattern looks come se fosse uno dei più facili da implementare (quando vedi per la prima volta Design Patters). È relativamente facile da fare, ma ci sono un paio di trucchi nella sua implementazione (tutti sono specifici per la lingua). Ma la parte più difficile dell'apprendimento di Singleton è; imparando quando usarli (che dovrebbe essere raramente (la maggior parte delle persone non discuterebbe mai, ma trovo difficile convincermi che non potrei mai usare un Singleton (pensavo che le poche volte che ho, la maggior parte sono stati errori (ma questo è come impariamo))).

    
risposta data 16.01.2011 - 19:56
fonte
13

L'unica volta che un singleton è utile, su una semplice variabile globale, è quando richiedi l'accesso globale ed è un errore avere più di un'istanza. Alcune persone usano i singleton per rappresentare i file di log, ma non è un errore avere più di una istanza della tua classe di log (ad esempio, potresti voler accedere a un file separato per qualche scopo particolare: if la tua classe di registro era un singleton, che ora è impossibile)

Si noti che non si tratta solo di richiedere l'accesso globale. È un accesso globale ed è un errore avere più di un'istanza.

Di solito, se hai bisogno di un accesso globale, una variabile globale sarà sufficiente (le persone non amano le variabili globali, ma i singleton non sono certamente una soluzione per l'uso eccessivo di variabili globali). Un approccio ancora migliore è spesso quello di utilizzare Programmazione orientata agli aspetti al posto di singleton e variabili globali.

    
risposta data 16.01.2011 - 20:19
fonte
5

Potresti trovare utile questo: link

Per riassumere:

  • il vantaggio di un singleton effettivo su una classe statica è che un singleton può implementare le interfacce
  • il punto di un singleton non è quello di concedere l'accesso globale a un valore, ma di controllare l'istanza di un tipo.

greetz
back2dos

    
risposta data 16.01.2011 - 21:26
fonte
2

I singleton hanno senso quando rappresentano qualcosa che è per sua natura intrinsecamente uno - di solito qualcosa con un'esistenza reale, anche se può avere senso quando rappresenta una risorsa statica di qualche tipo.

    
risposta data 17.01.2011 - 05:24
fonte
2

Senza esaminare quel thread, posso dirti che l'ho visto usato numerose volte solo come un involucro sottile attorno a una variabile globale. È come mettere il rossetto su un maiale ... Solo perché lo hai avvolto in uno schema di progettazione, non lo rende OK.

modifica: A quanto pare ho bisogno di spiegare perché i globals sono cattivi? Puoi leggere le informazioni generali qui se hai bisogno di un'introduzione.

"Scribes frequently use Singletons in a misguided attempt to replace global variables. I have, for example, been on projects where the Singleton has been described as 'a well-known object' -- does that not sound like a global variable, my child?"

"Umm... no, not really," I drawled after a bit of consideration. I wrote on my whiteboard:

S &S::Instance() 
{   
    static S theInstance;   
    return theInstance; 
}

"I don't see a global variable here." "Ah, my child, but there is a global variable -- a global variable named S::Instance(). Consider this parable:

class T { /* whatever */ }; 
T globalT;

"What is the difference between globalT and theInstance? Both variables have static storage duration, do they not?"

Pertanto, non creare mai un Singleton il cui unico scopo è mascherare una variabile globale.

    
risposta data 16.01.2011 - 19:27
fonte
2

Una cosa di cui bisogna fare attenzione con i singleton è assicurarsi che siano effettivamente single. Ad esempio, con Java se non si prendono alcune misure aggiuntive durante la creazione del singleton e si hanno molti thread che vogliono accedervi, si potrebbe finire per avere molte istanze del "singleton".

Inoltre, se hai un'applicazione che utilizza RMI e finisci per creare un "singleton" sul client e sul server, allora hai ancora un singleton?

So che questi sono solo esempi di Java, ma sto solo facendo alcuni punti. Il problema che molte persone citano è che alcuni oggetti che sembrano come dovrebbero essere singleton, in realtà non devono essere uno. Ad esempio, potrebbe essere utile avere una singola istanza di alcuni oggetti factory, ma non è necessario forzarla. Potresti solo crearne uno in modo esplicito, ma avere due persone in giro non spezzerebbe le cose.

    
risposta data 16.01.2011 - 19:51
fonte
1

Mettere il rossetto su un maiale. È così interessante che ho dovuto creare una nuova risposta:

Quindi significa che, per la registrazione ...

  • Non puoi creare singoletti sepatati per ogni bersaglio di registrazione, ad esempio logError () - > write, logWarning () - > write, etc (???)
  • Non è possibile selezionare il tipo di registro quando si ottiene il log Singleton (TYPE) - > write (???)
  • Non puoi semplicemente creare un'altra istanza di classe, quando necessario (puoi avere la stessa classe usando singleton per la registrazione "globale" e quindi puoi creare un'istanza per qualcosa di specifico) (???)

Quindi, a tuo avviso, cosa c'è di meglio che usare i singleton in questo caso?

  • Magari passando l'istanza della classe log ad ogni funzione in ogni oggetto di classe
  • Magari solo creando la classe di log su richiesta, e vorrà dire che dovrai aprire il blocco / chiudere il file tante volte quante hai righe (molto ottimali :)
  • Classe statica ... stesso problema. Le prestazioni faranno schifo ...
  • Funzioni globali (bel pasticcio)
  • Oggetti globali (di nuovo un bel pasticcio)

I singleton sono una buona pratica di progettazione perché puoi sempre modificare l'oggetto globale da qualche parte, o qualcun altro può semplicemente sovrascriverlo. Non possibile con il modello Singleton.

Cattivo feedback? Da sviluppatori non istruiti? :) Ok, diciamo che se si abusa un pattern lo troverebbero schifo, quindi dovremmo concludere che ogni schema di design fa schifo perché potrebbe essere abusato. E mySQL ha anche una brutta stampa su mongoDB :) Sai la parola "premere" è la chiave. La stampa è alla ricerca di sensazioni e i giornalisti non sanno davvero di cosa parlano.

Funzioni matematiche, chiunque? Math.max () ... bella idea di non creare un oggetto ogni volta che vuoi fare qualche semplice operazione di matematica, giusto? :)

Classe statica: la si utilizza quando non è necessario conservare lo stato o le risorse tra le chiamate di funzione (ad esempio, le funzioni matematiche, ognuna attiva non è correlata alla precedente e non richiede risorse di sistema). Per es. loggando usi singleton, perché vorresti mantenere FileSystem Object Handle per non aprirlo / chiuderlo più e più volte.

    
risposta data 16.01.2011 - 20:47
fonte

Leggi altre domande sui tag