Inversion of Control (IoC) può essere abbastanza confuso quando viene incontrato per la prima volta.
- Che cos'è?
- Quale problema risolve?
- Quando è appropriato usare e quando no?
Inversion of Control (IoC) può essere abbastanza confuso quando viene incontrato per la prima volta.
Risposte:
I modelli Inversion of Control (IoC) e Dependency Injection (DI) riguardano la rimozione delle dipendenze dal codice.
Ad esempio, supponiamo che l'applicazione abbia un componente dell'editor di testo e desideri fornire il controllo ortografico. Il tuo codice standard sarebbe simile al seguente:
public class TextEditor {
private SpellChecker checker;
public TextEditor() {
this.checker = new SpellChecker();
}
}
Quello che abbiamo fatto qui crea una dipendenza tra il TextEditor
e il SpellChecker
. In uno scenario IoC invece faremmo qualcosa del genere:
public class TextEditor {
private IocSpellChecker checker;
public TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}
Nel primo esempio di codice stiamo istanziando SpellChecker
( this.checker = new SpellChecker();
), il che significa che la TextEditor
classe dipende direttamente dalla SpellChecker
classe.
Nel secondo esempio di codice stiamo creando un'astrazione avendo la SpellChecker
classe di dipendenza nella TextEditor
firma del costruttore (non inizializzando la dipendenza in classe). Questo ci consente di chiamare la dipendenza e poi passarla alla classe TextEditor in questo modo:
SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);
Ora il client che crea la TextEditor
classe ha il controllo su quale SpellChecker
implementazione utilizzare perché stiamo iniettando la dipendenza nella TextEditor
firma.
L'inversione del controllo è ciò che si ottiene quando si richiamano i programmi, ad esempio come un programma gui.
Ad esempio, in un menu di vecchia scuola, potresti avere:
print "enter your name"
read name
print "enter your address"
read address
etc...
store in database
controllando così il flusso di interazione dell'utente.
In un programma di interfaccia grafica o qualcosa di simile, invece diciamo:
when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase
Quindi ora il controllo è invertito ... invece che il computer accetti l'input dell'utente in un ordine fisso, l'utente controlla l'ordine in cui i dati vengono immessi e quando i dati vengono salvati nel database.
Fondamentalmente, qualsiasi cosa con un loop di eventi, callback o trigger di esecuzione rientra in questa categoria.
Che cos'è Inversion of Control?
Se segui questi due semplici passaggi, hai fatto l'inversione del controllo:
Esistono diverse tecniche possibili per ciascuna di queste fasi in base alla tecnologia / linguaggio che si sta utilizzando per l'implementazione.
-
L' inversione di parte del Inversion of Control (IOC) è la cosa più confusione; perché inversione è il termine relativo. Il modo migliore per capire l'IoC è dimenticare quella parola!
-
Esempi
what-to-do
ewhen-to-do
L'inversione dei controlli riguarda la separazione delle preoccupazioni.
Senza IoC : hai un computer portatile e rompi accidentalmente lo schermo. E dannatamente, trovi che lo stesso modello di laptop non è presente sul mercato. Quindi sei bloccato.
Con IoC : hai un desktop computer e rompi accidentalmente lo schermo. Scopri che puoi semplicemente prendere quasi tutti i monitor desktop dal mercato e funziona bene con il tuo desktop.
Il tuo desktop implementa con successo l'IoC in questo caso. Accetta diversi tipi di monitor, mentre il laptop no, ha bisogno di uno schermo specifico per essere riparato.
Inversion of Control, (o IoC), si tratta di ottenere la libertà (Ti sposi, hai perso la libertà e sei controllato. Hai divorziato, hai appena implementato Inversion of Control. Questo è ciò che abbiamo chiamato "disaccoppiato". Un buon sistema informatico scoraggia una relazione molto stretta.) maggiore flessibilità (La cucina del tuo ufficio serve solo acqua di rubinetto pulita, questa è la tua unica scelta quando vuoi bere. Il tuo capo ha implementato Inversion of Control impostando una nuova macchina da caffè. Ora ottieni il flessibilità nella scelta di acqua di rubinetto o caffè.) e minore dipendenza(Il tuo partner ha un lavoro, non hai un lavoro, dipendi finanziariamente dal tuo partner, quindi sei controllato. Trovi un lavoro, hai implementato Inversion of Control. Un buon sistema informatico incoraggia la dipendenza.)
Quando usi un computer desktop, sei stato schiavo (o, diciamo, controllato). Devi sederti davanti a uno schermo e guardarlo. Usare la tastiera per scrivere e usare il mouse per navigare. E un software mal scritto può schiavizzarti ancora di più. Se sostituisci il tuo desktop con un laptop, allora hai un po 'invertito il controllo. Puoi facilmente prenderlo e muoverti. Quindi ora puoi controllare dove ti trovi con il tuo computer, anziché controllarlo dal tuo computer.
Implementando Inversion of Control, un consumatore di software / oggetti ottiene più controlli / opzioni sul software / oggetti, invece di essere controllato o avere meno opzioni.
Con le idee sopra in mente. Ci manca ancora una parte fondamentale di IoC. Nello scenario di IoC, il consumatore di software / oggetti è un framework sofisticato. Ciò significa che il codice che hai creato non viene chiamato da solo. Ora spieghiamo perché in questo modo funziona meglio per un'applicazione web.
Supponiamo che il tuo codice sia un gruppo di lavoratori. Devono costruire un'auto. Questi lavoratori hanno bisogno di un posto e strumenti (un framework software) per costruire la macchina. Un framework software tradizionale sarà come un garage con molti strumenti. Pertanto, i lavoratori devono elaborare autonomamente un piano e utilizzare gli strumenti per costruire l'auto. Costruire un'auto non è un affare facile, sarà davvero difficile per i lavoratori pianificare e collaborare adeguatamente. UN modernoil framework software sarà come una moderna fabbrica di automobili con tutte le strutture e i gestori in atto. I lavoratori non devono fare alcun piano, i gestori (parte del framework, sono le persone più intelligenti e hanno elaborato il piano più sofisticato) aiuteranno a coordinarsi in modo che i lavoratori sappiano quando fare il loro lavoro (framework chiama il tuo codice). I lavoratori devono solo essere abbastanza flessibili da utilizzare tutti gli strumenti che i manager danno loro (usando l'iniezione delle dipendenze).
Anche se i lavoratori danno il controllo della gestione del progetto ai massimi livelli ai gestori (il framework). Ma è bello che alcuni professionisti aiutino. Questo è veramente il concetto di IoC.
Le moderne applicazioni Web con un'architettura MVC dipendono dal framework per eseguire il routing URL e mettere in atto i controller affinché il framework chiami.
L'iniezione di dipendenza e l'inversione del controllo sono correlate. L'iniezione di dipendenza è a livello micro e Inversion of Control è a livello macro . Devi mangiare ogni boccone (implementare DI) per terminare un pasto (implementare IoC).
Prima di usare Inversion of Control dovresti essere ben consapevole del fatto che ha i suoi pro e contro e dovresti sapere perché lo usi.
Professionisti:
Contro:
Personalmente vedo i punti di forza di IoC e mi piacciono molto, ma tendo a evitare l'IoC ogni volta che è possibile perché trasforma il tuo software in una raccolta di classi che non costituisce più un programma "reale" ma solo qualcosa che deve essere messo insieme da Configurazione XML o metadati delle annotazioni e cadono (e cadono) senza di essa.
Articolo di Wikipedia . Per me, l'inversione del controllo sta trasformando il codice scritto in sequenza e trasformandolo in una struttura di delega. Invece del tuo programma che controlla esplicitamente tutto, il tuo programma imposta una classe o una libreria con determinate funzioni da chiamare quando accadono determinate cose.
Risolve la duplicazione del codice. Ad esempio, ai vecchi tempi scrivevi manualmente il tuo ciclo di eventi, eseguendo il polling delle librerie di sistema per nuovi eventi. Al giorno d'oggi, le più moderne API dite semplicemente alle librerie di sistema a quali eventi siete interessati e vi farà sapere quando si verificano.
L'inversione del controllo è un modo pratico per ridurre la duplicazione del codice e se ti ritrovi a copiare un intero metodo e a cambiare solo una piccola parte del codice, puoi considerare di affrontarlo con l'inversione del controllo. L'inversione del controllo è resa semplice in molte lingue attraverso il concetto di delegati, interfacce o persino puntatori di funzioni non elaborate.
Non è opportuno utilizzarlo in tutti i casi, poiché il flusso di un programma può essere più difficile da seguire quando viene scritto in questo modo. È un modo utile per progettare metodi quando si scrive una libreria che verrà riutilizzata, ma dovrebbe essere usata con parsimonia nel cuore del proprio programma a meno che non risolva davvero un problema di duplicazione del codice.
Ma penso che devi stare molto attento. Se userai eccessivamente questo modello, realizzerai un design molto complicato e un codice ancora più complicato.
Come in questo esempio con TextEditor: se hai un solo SpellChecker forse non è davvero necessario usare IoC? A meno che non sia necessario scrivere test unitari o qualcosa del genere ...
Comunque: sii ragionevole. I modelli di progettazione sono buone pratiche ma non la Bibbia da predicare. Non attaccarlo ovunque.
IoC / DI per me sta estromettendo dipendenze dagli oggetti chiamanti. Super semplice.
La risposta non tecnica è la possibilità di sostituire un motore in un'auto proprio prima di accenderlo. Se tutto si collega correttamente (l'interfaccia), sei bravo.
Supponi di essere un oggetto. E vai in un ristorante:
Senza IoC : chiedi "apple" e ti viene sempre servito apple quando chiedi di più.
Con IoC : puoi chiedere "frutto". Puoi ottenere diversi frutti ogni volta che vieni servito. ad esempio mela, arancia o anguria.
Quindi, ovviamente, l'IoC è preferito quando ti piacciono le varietà.
L'inversione del controllo è un modello utilizzato per disaccoppiare componenti e strati nel sistema. Il modello viene implementato iniettando dipendenze in un componente quando viene costruito. Queste dipendenze sono generalmente fornite come interfacce per un ulteriore disaccoppiamento e per supportare la testabilità. I contenitori IoC / DI come Castle Windsor, Unity sono strumenti (librerie) che possono essere utilizzati per fornire IoC. Questi strumenti offrono funzionalità estese oltre alla semplice gestione delle dipendenze, tra cui durata, AOP / Intercettazione, politica, ecc.
un. Allevia un componente dall'essere responsabile della gestione delle sue dipendenze.
b. Fornisce la possibilità di scambiare implementazioni di dipendenze in diversi ambienti.
c. Consente a un componente di essere testato attraverso il derisione delle dipendenze.
d. Fornisce un meccanismo per la condivisione di risorse in un'applicazione.
un. Critico durante lo sviluppo guidato dai test. Senza IoC può essere difficile testarlo, poiché i componenti sottoposti a test sono altamente accoppiati al resto del sistema.
b. Critico nello sviluppo di sistemi modulari. Un sistema modulare è un sistema i cui componenti possono essere sostituiti senza richiedere la ricompilazione.
c. Critico se ci sono molte preoccupazioni trasversali che devono essere affrontate, parzialmente in un'applicazione enterprise.
Rispondere solo alla prima parte. Che cos'è?
Inversion of Control (IoC) significa creare istanze di dipendenze prima e ultima istanza di una classe (facoltativamente iniettandole attraverso il costruttore), invece di creare prima un'istanza della classe e poi l'istanza della classe creando istanze di dipendenze. Pertanto, l'inversione del controllo inverte il flusso di controllo del programma. Invece della callee controllare il flusso di controllo (creando dipendenze), il chiamante controlla il flusso di controllo del programma .
Scriverò la mia semplice comprensione di questi due termini:
For quick understanding just read examples*
Iniezione di dipendenza (DI):
Iniezione di dipendenza generalmente significa passare un oggetto da quale metodo dipende, come parametro da un metodo, piuttosto che far sì che il metodo crei l'oggetto dipendente .
Ciò che significa in pratica è che il metodo non dipende direttamente da una particolare implementazione; qualsiasi implementazione che soddisfi i requisiti può essere passata come parametro.
Con questo gli oggetti raccontano le loro dipendenze. E la primavera lo rende disponibile.
Questo porta allo sviluppo di applicazioni vagamente accoppiate.
Quick Example:EMPLOYEE OBJECT WHEN CREATED,
IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
(if address is defines as dependency by Employee object)
Contenitore Inversion of Control (IoC):
caratteristica comune dei framework, il CIO gestisce gli oggetti java
- dall'istanza alla distruzione attraverso la sua BeanFactory.
-I componenti Java istanziati dal contenitore IoC sono chiamati bean e il contenitore IoC gestisce l'ambito di un bean, gli eventi del ciclo di vita e tutte le funzionalità AOP per le quali è stato configurato e codificato.
QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it
.
Implementando Inversion of Control, un consumatore di software / oggetti ottiene più controlli / opzioni sul software / oggetti, invece di essere controllato o avere meno opzioni.
L'inversione del controllo come linea guida di progettazione ha i seguenti scopi:
C'è un disaccoppiamento dell'esecuzione di un certo compito dall'implementazione.
Ogni modulo può concentrarsi su ciò per cui è progettato.
I moduli non fanno ipotesi su ciò che fanno gli altri sistemi ma fanno affidamento sui loro contratti.
La sostituzione dei moduli non ha alcun effetto collaterale su altri moduli
. Terrò le cose astratte qui. Puoi visitare i seguenti link per una comprensione dettagliata dell'argomento.
Una buona lettura con l'esempio
Sono d'accordo con NilObject , ma vorrei aggiungere a questo:
se ti ritrovi a copiare un intero metodo e a modificare solo una piccola parte del codice, puoi considerare di affrontarlo con l'inversione del controllo
Se ti ritrovi a copiare e incollare il codice, fai quasi sempre qualcosa di sbagliato. Codificato come principio di progettazione una volta e una volta sola .
Ad esempio, l'attività n. 1 è creare l'oggetto. Senza il concetto IOC, l'attività n. 1 dovrebbe essere eseguita dal programmatore, ma con il concetto IOC, l'attività n. 1 verrebbe eseguita dal contenitore.
In breve, il controllo viene invertito dal programmatore al contenitore. Quindi, si chiama come inversione di controllo.
Ho trovato un buon esempio qui .
Diciamo che facciamo qualche incontro in qualche hotel.
Molte persone, molte caraffe d'acqua, molti bicchieri di plastica.
Quando qualcuno vuole bere, riempie la tazza, beve e lancia la tazza sul pavimento.
Dopo un'ora o qualcosa del genere abbiamo un pavimento coperto di bicchieri di plastica e acqua.
Lascia invertire il controllo.
Lo stesso incontro nello stesso posto, ma invece di bicchieri di plastica abbiamo un cameriere con un bicchiere di vetro (Singleton)
e lei offre sempre agli ospiti che bevono.
Quando qualcuno vuole bere, ottiene dal bicchiere del cameriere, beve e lo restituisce al cameriere.
Tralasciando la questione dell'igiene, l'ultima forma di controllo del processo di abbeveraggio è molto più efficace ed economica.
E questo è esattamente ciò che fa Spring (un altro contenitore IoC, ad esempio: Guice). Invece di lasciare che l'applicazione crei ciò di cui ha bisogno usando una nuova parola chiave (prendendo tazza di plastica), il contenitore Spring IoC offre sempre all'applicazione la stessa istanza (singleton) dell'oggetto necessario (bicchiere d'acqua).
Pensa a te stesso come organizzatore di tale incontro. È necessario il modo di inviare messaggi all'amministrazione dell'hotel
i membri della riunione avranno bisogno di un bicchiere d'acqua ma non di un gioco da ragazzi.
Esempio:-
public class MeetingMember {
private GlassOfWater glassOfWater;
...
public void setGlassOfWater(GlassOfWater glassOfWater){
this.glassOfWater = glassOfWater;
}
//your glassOfWater object initialized and ready to use...
//spring IoC called setGlassOfWater method itself in order to
//offer to meetingMember glassOfWater instance
}
Link utili:-
Sembra che la cosa più confusa di "IoC", l'acronimo e il nome per cui si distingue è che è troppo glamour di un nome - quasi un nome rumoroso.
Abbiamo davvero bisogno di un nome con cui descrivere la differenza tra la programmazione procedurale e quella guidata dagli eventi? OK, se ne abbiamo bisogno, ma dobbiamo scegliere un nuovo nome "più grande della vita" che confonde più di quanto risolva?
Inversione di controllo è quando vai al negozio di alimentari e tua moglie ti dà l'elenco dei prodotti da acquistare.
In termini di programmazione, ha passato una funzione di callback getProductList()
alla funzione che stai eseguendo -doShopping()
.
Consente all'utente della funzione di definirne alcune parti, rendendola più flessibile.
getProductList()
ti chiama per trovare la fonte di denaro, significa che il controllo è al tuo fianco. In caso di inversione, controllerà, anche i soldi che fornirà per acquistare.
Ho trovato un esempio molto chiaro qui che spiega come il "controllo è invertito".
Codice classico (senza iniezione di dipendenza)
Ecco come funzionerà approssimativamente un codice che non utilizza DI:
Utilizzo dell'iniezione di dipendenza
Ecco come funzionerà approssimativamente un codice che utilizza DI:
Il controllo delle dipendenze viene invertito da una chiamata a quella chiamata.
Quali problemi risolve?
L'iniezione delle dipendenze semplifica lo scambio con la diversa implementazione delle classi iniettate. Durante il test unitario è possibile iniettare un'implementazione fittizia, che rende il test molto più semplice.
Es .: Supponiamo che la tua applicazione memorizzi il file caricato dall'utente in Google Drive, con DI il tuo codice controller potrebbe apparire così:
class SomeController
{
private $storage;
function __construct(StorageServiceInterface $storage)
{
$this->storage = $storage;
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
class GoogleDriveService implements StorageServiceInterface
{
public function authenticate($user) {}
public function putFile($file) {}
public function getFile($file) {}
}
Quando cambiano le tue esigenze, invece di Google Drive ti viene chiesto di utilizzare Dropbox. Devi solo scrivere un'implementazione di dropbox per StorageServiceInterface. Non è necessario apportare modifiche al controller finché l'implementazione di Dropbox aderisce a StorageServiceInterface.
Durante il test è possibile creare il finto per StorageServiceInterface con l'implementazione fittizia in cui tutti i metodi restituiscono null (o qualsiasi valore predefinito secondo il requisito di test).
Invece se avessi la classe controller per costruire l'oggetto di archiviazione con la new
parola chiave in questo modo:
class SomeController
{
private $storage;
function __construct()
{
$this->storage = new GoogleDriveService();
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
Quando vuoi cambiare con l'implementazione di Dropbox devi sostituire tutte le linee in cui new
è costruito l'oggetto GoogleDriveService e utilizzare DropboxService. Inoltre, durante il test della classe SomeController, il costruttore si aspetta sempre la classe GoogleDriveService e vengono attivati i metodi effettivi di questa classe.
Quando è appropriato e quando no? Secondo me usi DI quando pensi che ci siano (o ci possano essere) implementazioni alternative di una classe.
Una spiegazione scritta molto semplice può essere trovata qui
http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html
Dice -
"Qualsiasi applicazione non banale è composta da due o più classi che collaborano tra loro per eseguire alcune logiche aziendali. Tradizionalmente, ogni oggetto è responsabile di ottenere i propri riferimenti agli oggetti con cui collabora (le sue dipendenze). Quando si applica DI, il gli oggetti ricevono le loro dipendenze al momento della creazione da qualche entità esterna che coordina ciascun oggetto nel sistema. In altre parole, le dipendenze vengono iniettate negli oggetti. "
Inversion of Control è un principio generico, mentre Dependency Injection realizza questo principio come modello di progettazione per la costruzione di grafici di oggetti (ovvero la configurazione controlla il modo in cui gli oggetti si riferiscono l'un l'altro, piuttosto che l'oggetto stesso controlla come ottenere il riferimento a un altro oggetto).
Guardando Inversion of Control come modello di progettazione, dobbiamo guardare a ciò che stiamo invertendo. L'iniezione di dipendenza inverte il controllo della costruzione di un grafico di oggetti. Se detto in parole povere, l'inversione del controllo implica un cambiamento nel flusso di controllo nel programma. Per esempio. Nell'app standalone tradizionale, abbiamo il metodo principale, da cui il controllo viene passato ad altre librerie di terze parti (nel caso in cui abbiamo utilizzato la funzione di libreria di terze parti), ma attraverso l'inversione del controllo di controllo viene trasferito dal codice della libreria di terze parti al nostro codice , poiché stiamo prendendo il servizio di libreria di terze parti. Ma ci sono altri aspetti che devono essere invertiti all'interno di un programma, ad es. Invocazione di metodi e thread per eseguire il codice.
Per coloro che sono interessati a una maggiore profondità su Inversion of Control è stato pubblicato un documento che delinea un quadro più completo di Inversion of Control come modello di progettazione (OfficeFloor: utilizzo di modelli di ufficio per migliorare la progettazione del software http://doi.acm.org/10.1145/ 2739011.2739013 con una copia gratuita disponibile per il download da http://www.officefloor.net/about.html ).
Ciò che viene identificato è la seguente relazione:
Inversione del controllo (per metodi) = Dipendenza (stato) Iniezione + Iniezione continua + Iniezione filo
Riepilogo della relazione precedente per Inversion of Control disponibile - http://dzone.com/articles/inversion-of-coupling-control
IoC riguarda l'inversione della relazione tra il codice e il codice di terze parti (libreria / framework):
DI (Dependency Injection) riguarda il flusso del controllo nell'applicazione. L'applicazione desktop tradizionale aveva un flusso di controllo dall'applicazione (metodo main ()) ad altre chiamate al metodo della libreria, ma con il flusso di controllo DI è invertito, il framework si occupa di avviare l'app, inizializzarla e invocare i metodi ogni volta che è necessario.
Alla fine vinci sempre :)
Mi piace questa spiegazione: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/
Inizia in modo semplice e mostra anche esempi di codice.
Il consumatore, X, ha bisogno della classe consumata, Y, per realizzare qualcosa. È tutto buono e naturale, ma X ha davvero bisogno di sapere che usa Y?
Non è sufficiente che X sappia che usa qualcosa che ha il comportamento, i metodi, le proprietà ecc. Di Y senza sapere chi implementa effettivamente il comportamento?
Estraendo una definizione astratta del comportamento usato da X in Y, illustrata come di seguito, e lasciando che il consumatore X usi un'istanza di quella invece di Y, può continuare a fare ciò che fa senza dover conoscere i dettagli su Y.
Nell'illustrazione sopra Y implementa I e X usa un'istanza di I. Mentre è abbastanza possibile che X usi ancora Y ciò che è interessante è che X non lo sa. Sa solo che usa qualcosa che implementa I.
Leggi l'articolo per ulteriori informazioni e descrizione di vantaggi quali:
...
Capisco che la risposta è già stata data qui. Ma penso ancora, alcune basi sull'inversione del controllo devono essere discusse qui a lungo per i futuri lettori.
Inversion of Control (IoC) è stato costruito su un principio molto semplice chiamato Principio di Hollywood . E dice che
Non chiamarci, ti chiameremo
Ciò significa che non andare a Hollywood per realizzare il tuo sogno, piuttosto se sei degno, allora Hollywood ti troverà e realizzerà il tuo sogno. Praticamente invertito, eh?
Ora, quando discutiamo del principio dell'IoC, ci dimentichiamo di Hollywood. Per l'IoC, ci devono essere tre elementi, un Hollywood, tu e un compito come realizzare il tuo sogno.
Nel nostro mondo di programmazione, Hollywood rappresentano un framework generico (può essere scritto da te o qualcun altro), si dichiara il codice utente che hai scritto e l'operazione rappresenti la cosa che si vuole realizzare con il vostro codice. Ora non devi mai avviare il tuo compito da solo, non in IoC! Piuttosto hai progettato tutto in modo tale che il tuo framework attiverà il tuo compito per te. Così hai costruito un quadro riutilizzabile che può rendere qualcuno un eroe o un altro un cattivo. Ma quel quadro è sempre al comando, sa quando scegliere qualcuno e che qualcuno sa solo cosa vuole essere.
Un esempio di vita reale sarebbe dato qui. Supponiamo che tu voglia sviluppare un'applicazione web. Quindi, crei un framework che gestirà tutte le cose comuni che un'applicazione web dovrebbe gestire come la gestione delle richieste http, la creazione di menu delle applicazioni, la pubblicazione di pagine, la gestione dei cookie, l'attivazione di eventi ecc.
E poi lasci alcuni hook nel tuo framework in cui puoi inserire ulteriori codici per generare menu, pagine, cookie personalizzati o la registrazione di alcuni eventi utente ecc. Su ogni richiesta del browser, il tuo framework verrà eseguito ed eseguirà i tuoi codici personalizzati se agganciati, quindi servili indietro al browser.
Quindi, l'idea è praticamente semplice. Invece di creare un'applicazione utente che controllerà tutto, per prima cosa crei un framework riutilizzabile che controllerà tutto, quindi scrivi i tuoi codici personalizzati e aggancialo al framework per eseguirli in tempo.
Laravel ed EJB sono esempi di tali framework.
Riferimento:
Parlare di programmazione
IoC in termini semplici: è l'uso di Interface come un modo per qualcosa di specifico (un campo o un parametro) come jolly che può essere utilizzato da alcune classi. Permette la riusabilità del codice.
Ad esempio, diciamo che abbiamo due classi: cane e gatto . Entrambi condividono le stesse qualità / stati: età, dimensioni, peso. Quindi, invece di creare una classe di servizio chiamata DogService e CatService , posso crearne una singola chiamata AnimalService che consente di utilizzare Dog e Cat solo se utilizzano l'interfaccia IAnimal .
Tuttavia, dal punto di vista pragmatico, ha alcuni arretrati.
a) La maggior parte degli sviluppatori non sa come usarlo . Ad esempio, posso creare una classe chiamata Customer e posso creare automaticamente (usando gli strumenti dell'IDE) un'interfaccia chiamata ICustomer . Quindi, non è raro trovare una cartella piena di classi e interfacce, non importa se le interfacce verranno riutilizzate o meno. Si chiama BLOATED. Alcune persone potrebbero sostenere che "in futuro potremmo usarlo". : - |
b) Ha alcuni limiti. Ad esempio, parliamo del caso di Dog and Cat e voglio aggiungere un nuovo servizio (funzionalità) solo per i cani. Diciamo che voglio calcolare il numero di giorni di cui ho bisogno per addestrare un cane ( trainDays()
), per il gatto è inutile, i gatti non possono essere addestrati (sto scherzando).
b.1) Se aggiungo trainDays()
al servizio AnimalService , funziona anche con i gatti e non è affatto valido.
b.2) Posso aggiungere una condizione in trainDays()
cui valuta quale classe viene utilizzata. Ma romperà completamente l'IoC.
b.3) Posso creare una nuova classe di servizio chiamata DogService solo per le nuove funzionalità. Ma aumenterà la manutenibilità del codice perché avremo due classi di servizio (con funzionalità simili) per Dog ed è un male.
Ho letto molte risposte per questo, ma se qualcuno è ancora confuso e ha bisogno di un "termine laico" più per spiegare l'IoC, ecco la mia opinione:
Immagina un genitore e un figlio che parlano tra loro.
Senza IoC:
* Genitore : puoi parlare solo quando ti faccio domande e puoi agire solo quando ti do il permesso.
Genitore : Questo significa che non puoi chiedermi se puoi mangiare, giocare, andare in bagno o persino dormire se non te lo chiedo.
Genitore : vuoi mangiare?
Bambino : No.
Genitore : Ok, tornerò. Aspettami.
Bambino : (Vuole giocare, ma poiché non ci sono domande da parte del genitore, il bambino non può fare nulla).
Dopo 1 ora...
Genitore : Sono tornato. Vuoi giocare?
Bambino : Sì.
Genitore : autorizzazione concessa.
Bambino : (finalmente è in grado di giocare).
Questo semplice scenario spiega che il controllo è centrato sul genitore. La libertà del bambino è limitata e dipende fortemente dalla domanda del genitore. Il bambino può parlare SOLO quando gli viene chiesto di parlare e può agire SOLO quando viene concesso il permesso.
Con IoC:
Il bambino ha ora la possibilità di porre domande e il genitore può rispondere con risposte e autorizzazioni. Significa semplicemente che il controllo è invertito! Il bambino è ora libero di porre domande in qualsiasi momento e sebbene ci sia ancora dipendenza con il genitore per quanto riguarda le autorizzazioni, non è dipendente dal modo di parlare / porre domande.
In un modo tecnologico di spiegazione, questo è molto simile all'interazione console / shell / cmd vs GUI. (Che è la risposta di Mark Harrison sopra la risposta n. 2 in alto). Nella console, sei dipendente da ciò che ti viene chiesto / visualizzato e non puoi passare ad altri menu e funzionalità senza rispondere prima alla domanda; seguendo un flusso sequenziale rigoroso. (programmaticamente questo è come un ciclo metodo / funzione). Tuttavia, con la GUI, i menu e le funzionalità sono strutturati e l'utente può selezionare tutto ciò di cui ha bisogno, avendo così un maggiore controllo ed essendo meno limitato. (a livello di programmazione, i menu hanno richiamata quando sono selezionati e ha luogo un'azione).
L'inversione del controllo riguarda il trasferimento del controllo dalla libreria al client. Ha più senso quando parliamo di un client che inietta (passa) un valore di funzione (espressione lambda) in una funzione di ordine superiore (funzione di libreria) che controlla (cambia) il comportamento della funzione di libreria. Un client o un framework che inietta dipendenze di libreria (che comportano comportamenti) in librerie può anche essere considerato IoC
Dal momento che ci sono già molte risposte alla domanda, ma nessuna mostra la rottura del termine Controllo inversione vedo l'opportunità di dare una risposta più concisa e utile.
L'inversione del controllo è un modello che implementa il principio di inversione di dipendenza (DIP). DIP afferma quanto segue: 1. I moduli di alto livello non dovrebbero dipendere da moduli di basso livello. Entrambi dovrebbero dipendere da astrazioni (ad es. Interfacce). 2. Le astrazioni non dovrebbero dipendere dai dettagli. I dettagli (implementazioni concrete) dovrebbero dipendere dalle astrazioni.
Esistono tre tipi di inversione del controllo:
I provider di inversione dell'interfaccia non devono definire un'interfaccia. Invece, il consumatore dovrebbe definire l'interfaccia e i provider devono implementarla. Interface Inversion consente di eliminare la necessità di modificare il consumatore ogni volta che viene aggiunto un nuovo provider.
Inversione del flusso Cambia il controllo del flusso. Ad esempio, hai un'applicazione console in cui hai chiesto di inserire molti parametri e dopo ogni parametro inserito sei costretto a premere Invio. È possibile applicare Flow Inversion qui e implementare un'applicazione desktop in cui l'utente può scegliere la sequenza di immissione dei parametri, l'utente può modificare i parametri e, nel passaggio finale, l'utente deve premere Invio una sola volta.
Inversione della creazione Può essere implementata dai seguenti modelli: modello di fabbrica, localizzatore di servizio e iniezione di dipendenza. Creation Inversion aiuta ad eliminare le dipendenze tra i tipi spostando il processo di creazione degli oggetti di dipendenza al di fuori del tipo che utilizza questi oggetti di dipendenza. Perché le dipendenze sono cattive? Ecco un paio di esempi: la creazione diretta di un nuovo oggetto nel codice rende i test più difficili; è impossibile cambiare i riferimenti negli assiemi senza ricompilazione (violazione del principio OCP); non è possibile sostituire facilmente un'interfaccia utente desktop con un'interfaccia utente Web.
Quindi numero 1 sopra . Che cos'è Inversion of Control?
La manutenzione è la prima cosa che risolve per me. Garantisce che sto usando le interfacce in modo che due classi non siano intime tra loro.
Utilizzando un contenitore come Castle Windsor, risolve ancora meglio i problemi di manutenzione. Essere in grado di sostituire un componente che va in un database con uno che utilizza la persistenza basata su file senza cambiare una riga di codice è fantastico (modifica della configurazione, il gioco è fatto).
E una volta che vai in generici, diventa ancora meglio. Immagina di avere un editore di messaggi che riceve record e pubblica messaggi. Non importa cosa pubblica, ma ha bisogno di un mappatore per prendere qualcosa da un record a un messaggio.
public class MessagePublisher<RECORD,MESSAGE>
{
public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
{
//setup
}
}
L'ho scritto una volta, ma ora posso inserire molti tipi in questo set di codice se pubblico diversi tipi di messaggi. Posso anche scrivere mappatori che registrano un record dello stesso tipo e li mappano su messaggi diversi. L'uso di DI con Generics mi ha dato la possibilità di scrivere pochissimo codice per svolgere molte attività.
Oh sì, ci sono problemi di testabilità, ma sono secondari ai vantaggi di IoC / DI.
Sto sicuramente amando IoC / DI.
3 Diventa più appropriato nel momento in cui hai un progetto di medie dimensioni leggermente più complesso. Direi che diventa appropriato nel momento in cui inizi a provare dolore.
La creazione di un oggetto all'interno della classe si chiama accoppiamento stretto, Spring rimuove questa dipendenza seguendo uno schema di progettazione (DI / IOC). In quale oggetto di classe in è passato a costruttore anziché a creare in classe. Più oltre diamo variabili di riferimento superclasse nel costruttore per definire una struttura più generale.