Cos'è una relazione tra Iniezione delle dipendenze, singola istanza e singleton?

2

Ho letto So Singletons sono cattivi, allora cosa? che è stata una grande spiegazione dell'iniezione di dipendenza come soluzione per inversione di controllo. Il presupposto assunto singleton e single instance erano sinonimi e, come altri hanno sottolineato singleton, è un esempio più restrittivo di istanza singola.

La mia domanda è: perché il rispondente è passato da una singola istanza a parlare di un'iniezione di dipendenza? Dichiara:

A cache does not need to be a singleton. It may need to be a single instance if you want to avoid fetching the same data for multiple cache instances; but that does not mean you actually have to expose everything to everyone.

Con DI, hai un'interfaccia, in questo caso "Cache". Tuttavia, hai più istanze. Istanze di VideoPage + istanze di MyAccountPage + ecc. VideoPage implementa IMediaCache che estende Cache . Il DI è che la classe dipendente che fa uso di questa astrazione di caching lo fa utilizzando l'interfaccia Cache come un tipo in un elenco di parametri (elenco di parametri del costruttore se si utilizza l'iniezione del costruttore, ecc.)

Quindi ci sono più istanze ( x VideoPages , y MyAccountPages , ecc.) La Cache è la cosa "singola" in questo modello di progettazione, ma non è un'istanza dato che non è possibile creare un'istanza di un'interfaccia.

"Single instance" e "Dependency Injection" sono idee separate, quindi la risposta mi ha confuso.

Inoltre non so perché la gente dice che l'iniezione di dipendenza è un'alternativa ai singleton. Un singleton forza un'istanza anche se provo a istanziare di nuovo. Per quanto riguarda l'iniezione di dipendenza, di nuovo, qual è la mia "singola istanza"? Il Cache non è, come ho spiegato prima. E ci sono più istanze di classi che in definitiva implementano l'interfaccia Cache .

    
posta user3148156 13.12.2014 - 06:09
fonte

2 risposte

2

Perché il contenitore per l'iniezione di dipendenza può e viene utilizzato per la gestione a vita. Fondamentalmente, lo scopo principale di singleton è di mantenere la durata di esattamente un'istanza: viene creato una volta all'avvio (o il primo utilizzo) e viene distrutto quando l'applicazione termina. Ma se metti sia la gestione della vita sia il comportamento in una singola classe (ad esempio Singleton), infrangi il principio di responsabilità singola.

D'altra parte, se si dispone di un singolo contenitore superiore, utilizzarlo per gestire la durata di quell'istanza, in base all'interfaccia. È possibile indicare il contenitore DI per gestire quella implementazione dell'interfaccia come singleton. Quindi restituisce la stessa istanza ogni volta che viene richiesta. Esistono anche diverse durate: per-thread, per- (web) request, ecc.

Se si utilizza DI anziché il campo statico, la progettazione attorno a questa singola istanza diventa molto più pulita. Inoltre, renderà più semplice cambiare idea in seguito, se ti rendi conto che ciò che pensavi fosse un singleton in realtà non lo è.

    
risposta data 13.12.2014 - 06:51
fonte
1

My question is, why did the responder go from single instance to talking about dependency injection?

Perché Dipendenza Iniezione (DI) è un modo per garantire che una classe abbia solo una singola istanza. L'uso del modello di design singleton è un altro.

Se configuri il tuo DI setup per restituire la stessa istanza ogni volta che qualcuno ne chiede uno, l'istanza diventa essenzialmente un singleton.

I also don't know why people saying dependency injection is an alternative to singletons. A singleton forces one instance even if I try to instantiate again. As for dependency injection, again, what is my "single instance"?

Quando utilizzi DI non devi creare istanze tu stesso. Invece ti affidi al framework DI per fornirglieli.

Questo significa che chiedi al framework DI di darti una cache. Se il framework DI restituisce la stessa istanza ogni volta, la cache è "un singleton" anche se la classe che implementa la cache non utilizza il modello di progettazione singleton.

Poiché "singleton" è potenzialmente confuso, è meglio dire che la tua cache è una "singola istanza" a meno che il contesto non sia chiaro.

With DI, you have one interface, in this case "Cache". However, you have multiple instances. ...

Penso che tu abbia frainteso l'esempio. VideoPage non implementa l'interfaccia IMediaCache . dipende da una classe che implementa l'interfaccia IMediaCache .

Le classi che implementano IMediaCache potrebbero essere qualcosa come MediaMemoryCache o MediaDiskCache .

VideoPage dipende da un'interfaccia anziché da un'implementazione concreta perché non dovrebbe preoccuparsi di come i dati vengono memorizzati nella cache, solo che lo è.

Ogni volta che l'utente apre la pagina video, il framework DI inietta una cache nella pagina.

Se il framework DI inietta la stessa istanza ogni volta, la cache è essenzialmente a singleton perché si comporta come un singleton senza esserne effettivamente uno. Questa è la istanza singola di cui parla il rispondente.

Poiché utilizzi un'interfaccia, puoi modificare l'implementazione concreta senza dover modificare VideoPage . Tutto ciò che devi fare è riconfigurare DI per iniettare SuperVideoCache piuttosto che MediaDiskCache .

Confrontalo con una vera implementazione "singleton":

Dovresti cambiare tutte le classi che attualmente usano MediaDiskCache.getInstance() per usare SuperVideoCache.getInstance() per cambiare l'implementazione della cache.

    
risposta data 28.01.2017 - 16:19
fonte

Leggi altre domande sui tag