[Prima di iniziare, lasciatemi dire che sono principalmente un programmatore Java, con solo un po 'di conoscenza di PHP. Ma io semplicemente cerco di ottenere i concetti più importanti in tutto, senza specificità linguistiche]
Dependency Injection si basa su due parti di codice:.
- Edilizia
- Esecuzione
In la sua forma più estrema, non ci sono operatori new
da trovare nella parte Esecuzione. Tutti loro sono trasferiti nella parte di costruzione. (In pratica, questo sarà attenuato.)
Tutte le costruzioni avvengono - nella parte di costruzione. Crea il grafico degli oggetti necessari per l'esecuzione dal basso verso l'alto. Quindi supponiamo, dovrebbe costruire un:
- A dipende da B, e
- B dipende C.
Poi
- C è costruito prima.
- Quindi B è costruito con C come parametro.
- Quindi A è costruito con B come parametro.
Quindi C non deve essere passato come parametro costruttore ad A. Questo piccolo esempio non illustra abbastanza fortemente, quanto questo riduce la quantità di oggetti che devono essere passati a un numero abbastanza piccolo numero.
Lo stesso iniettore di dipendenza non deve essere trasferito nella parte di esecuzione. Questo è uno degli errori fondamentali che tutti (incluso me stesso) cercano di fare, quando entrano in contatto per la prima volta con DI. Il problema è che questo annullerebbe completamente le linee tra Costruzione ed Esecuzione. Un altro modo per dirlo è che violerebbe lo Law of Demeter. O nel pattern speak: alla fine "degraderebbe" il pattern dell'iniezione di dipendenza nel pattern di localizzazione del servizio. È discutibile, se questo è davvero un degrado, ma in ogni caso di solito non è una buona idea abusare del filtro di dipendenza come localizzatore di servizio.
Quindi, ogni volta che è necessario assegnare a uno degli oggetti costruiti la possibilità di produrre altri oggetti durante l'esecuzione, anziché passare l'iniettore di dipendenze, si passa solo a provider semplici (un termine utilizzato dal framework DI ID Guice). Queste sono classi piuttosto semplici che possono solo creare un certo tipo di oggetto. Hanno somiglianze con una fabbrica.
Prima prova a passare le dipendenze richieste direttamente al costruttore.
Quindi, per riassumere:
- costruire oggetti bottom-up.
- Passa solo il minor numero di dipendenze necessarie per creare un oggetto.
- Una volta terminato, iniziare l'esecuzione.
- Durante l'esecuzione, è ancora possibile recuperare gli oggetti appena creati utilizzando i provider.
Ma non prenderlo troppo lontano: oggetti semplici possono ancora essere creati senza un provider :-)
E ora, tutto quello che dovrete fare è di tradurre questa roba in codice di qualità. Forse altri possono aiutarti con alcuni esempi di PHP.
Addendum: Un po 'di più su Provider
Come notato sopra, la nozione di "Provider" (una fabbrica specializzata) è un po' specifico per il framework Java DI Guice. Questo framework può creare automaticamente un Provider per qualsiasi tipo di oggetto. Tuttavia, il concetto è generalmente utile per DI. L'unica differenza è che senza l'aiuto di Guice o di un framework simile, dovrai scrivere tu stesso i provider, ma è abbastanza semplice:
Diciamo che B dipende da C.
- Se B ha solo bisogno di una sola istanza fissa di C, quindi non è necessario un provider - si può semplicemente costruire B con l'argomento del costruttore C.
- Se B ha bisogno di creare più istanze di C durante l'esecuzione , quindi basta scrivere una classe chiamata
CProvider
con un metodo get()
, che può creare una nuova istanza di C. Quindi passare un'istanza di CProvider
nel costruttore di B e memorizzare il Provider in un campo istanza di B. Ora B può chiamare cProvider.get()
quando ha bisogno di una nuova istanza di C.
I provider sono parte del codice di costruzione, quindi è consentito utilizzare new C(...)
! D'altra parte, non fanno parte del codice di esecuzione, quindi non dovresti avere alcuna logica di esecuzione.
CProvider
possono essere passati a più costruttori, ovviamente. Puoi anche scrivere più versioni CProvider1
, CProvider2
, ... - dove ognuno può costruire versioni diverse di oggetti C con proprietà differenti. Oppure è semplice istanziare CProvider
più volte con argomenti diversi.
Insightful, grazie per la spiegazione. Conosco il modello di Service Locator e non è quello che sto cercando di realizzare. Potresti per favore elaborare un po 'sull'uso dei provider? – Andre
Aggiunta di un addendum. Fammi sapere, se hai bisogno di maggiori informazioni. –
Grazie mille per l'aiuto. Fondamentalmente ho bisogno di passare i fornitori richiesti per ogni dipendenza a più istanze. Questi sono fondamentalmente modelli di fabbrica ma specifici per creare oggetti per uno scopo (potrebbe essere una varietà di classi, un esempio sarebbe driver di output) e restituirli alla classe dipendente. Sembra più complessità in arrivo: D – Andre