Co to jest odwrócenie kontroli?

1825

Inwersja kontroli (IoC) może być dość myląca, gdy zostanie po raz pierwszy napotkana.

  1. Co to jest?
  2. Który problem rozwiązuje?
  3. Kiedy należy używać, a kiedy nie?
Mike Minutillo
źródło
292
Problemem większości tych odpowiedzi jest stosowana terminologia. Co to jest pojemnik? Odwrócenie? Zależność? Wyjaśnij to w sposób laicki bez wielkich słów.
kirk.burleson
13
Zobacz także na Programmers.SE: Dlaczego Inversion of Control ma taką nazwę?
Izkata
8
To jest Dependency Injection (DI) - patrz opis Martina Fowlersa
Ricardo Sanchez
7
To zdjęcie w
pewnym sensie
To przymiotnik, nie rzeczownik, to nie rzecz, to opis zmiany dokonanej w kodzie, w której kontrola przepływu odbywa się w delegacie, a nie w kontenerze.
Martin Spamer,

Odpowiedzi:

1523

Wzorce Inversion of Control (IoC) i Dependency Injection (DI) polegają na usuwaniu zależności z kodu.

Załóżmy na przykład, że Twoja aplikacja ma edytor tekstu i chcesz sprawdzić pisownię. Twój standardowy kod wyglądałby mniej więcej tak:

public class TextEditor {

    private SpellChecker checker;

    public TextEditor() {
        this.checker = new SpellChecker();
    }
}

To, co tutaj zrobiliśmy, tworzy zależność między TextEditori SpellChecker. W scenariuszu IoC zamiast tego zrobilibyśmy coś takiego:

public class TextEditor {

    private IocSpellChecker checker;

    public TextEditor(IocSpellChecker checker) {
        this.checker = checker;
    }
}

W pierwszym przykładzie kodu tworzymy instancję SpellChecker( this.checker = new SpellChecker();), co oznacza, że TextEditorklasa zależy bezpośrednio od SpellCheckerklasy.

W drugim przykładzie kodu tworzymy abstrakcję, mając SpellCheckerklasę zależności w TextEditorsygnaturze konstruktora (nie inicjując zależności w klasie). Dzięki temu możemy wywołać zależność, a następnie przekazać ją do klasy TextEditor w następujący sposób:

SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);

Teraz klient tworzący TextEditorklasę ma kontrolę nad tym, której SpellCheckerimplementacji użyć, ponieważ wprowadzamy zależność do TextEditorpodpisu.

urini
źródło
50
Dobry jasny przykład. Załóżmy jednak, że zamiast wymagać, aby interfejs ISpellChecker był przekazywany do konstruktora obiektu, ujawniliśmy go jako ustawialną właściwość (lub metodę SetSpellChecker). Czy nadal stanowiłoby to IoC?
devios1,
25
chainguy1337 - tak by to zrobiło. Użycie takich ustawiaczy nazywa się zastrzykiem ustawiającym w przeciwieństwie do wstrzykiwania konstruktora (obie techniki wstrzykiwania zależności). IoC to dość ogólny wzorzec, ale bolą ją iniekcje zależności IoC
Jack Ukleja
257
Pomimo wielu głosów pozytywnych, ta odpowiedź jest nieprawidłowa. Zobacz martinfowler.com/articles/injection.html#InversionOfControl . W szczególności zwróć uwagę na część „Inwersja kontroli jest zbyt ogólnym terminem, dlatego ludzie uważają go za mylący. W wyniku wielu dyskusji z różnymi zwolennikami IoC zdecydowaliśmy się na nazwę Dependency Injection”.
Rogério
45
Zgadzam się z @Rogeria. to nie wyjaśnia, dlaczego nazywa się to IoC i jestem zaskoczony liczbą głosów ;-)
Aravind Yarram,
31
Popieram @Rogerio i @Pangea. Może to być dobry przykład wstrzyknięcia konstruktora, ale nie dobra odpowiedź na pierwotne pytanie. IoC, zgodnie z definicją Fowlera , można zrealizować bez użycia jakiegokolwiek zastrzyku, np. Za pomocą lokalizatora usług lub nawet zwykłego dziedziczenia.
mtsz
642

Odwrócenie kontroli jest tym, co dostajesz, gdy Twój program wywołuje zwrotne, np. Jak program GUI.

Na przykład w menu starej szkoły możesz mieć:

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

kontrolując w ten sposób przepływ interakcji użytkownika.

W programie GUI lub jakimś innym, zamiast tego mówimy:

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

Teraz kontrola jest odwrócona ... zamiast komputera akceptującego dane wejściowe użytkownika w ustalonej kolejności, użytkownik kontroluje kolejność wprowadzania danych i zapisywania danych w bazie danych.

Zasadniczo wszystko , co zawiera pętlę zdarzeń, wywołania zwrotne lub wyzwalacze, należy do tej kategorii.

Mark Harrison
źródło
161
nie zaznaczaj tego faceta. technicznie ma rację martinfowler.com/bliki/InversionOfControl.html IoC jest bardzo ogólną zasadą . Przepływ kontroli jest „odwrócony” przez wstrzyknięcie zależności, ponieważ skutecznie delegowano zależności do jakiegoś systemu zewnętrznego (np. Kontener IoC)
Jack Ukleja,
38
Zgodził się z komentarzem Schneidera. 5 głosów negatywnych? Umysł drży, ponieważ jest to jedyna prawdziwa odpowiedź. Zwróć uwagę na otwarcie: „ jak program GUI”. Zastrzyk zależności jest tylko najczęściej spotykaną realizacją IoC.
Jeff Sternal
40
Rzeczywiście, jest to jedna z niewielu poprawnych odpowiedzi! Ludzie, IoC nie polega zasadniczo na zależnościach. Ani trochę.
Rogério
13
+1 - To jest dobry opis (z przykładem) następującej wypowiedzi Martina Fowlera: „Wczesne interfejsy użytkownika były kontrolowane przez aplikację. Miałbyś sekwencję poleceń takich jak„ Wprowadź nazwę ”,„ wprowadź adres ”; twój program sterował monitami i odbierał odpowiedzi na każde z nich. W graficznych (lub nawet ekranowych) interfejsach użytkownika interfejs zawierałby tę główną pętlę, a program zamiast tego zapewniał obsługę zdarzeń dla różnych pól na ekranie. program został odwrócony, przeniesiony z dala od ciebie do frameworka. ”
Ashish Gupta
14
Rozumiem teraz, dlaczego czasami jest żartobliwie nazywany „zasadą Hollywood: nie dzwoń do nas, zadzwonimy do ciebie”
Alexander Suraphel
419

Co to jest odwrócenie kontroli?

Jeśli wykonasz te dwa proste kroki, dokonałeś odwrócenia kontroli:

  1. Oddzielić co -to-zrobić udział od kiedy -to-nie rozłączy.
  2. Upewnić się, że gdy część wie, jak niewiele , jak to możliwe o jakiej części; i wzajemnie.

Istnieje kilka technik dla każdego z tych kroków w zależności od technologii / języka używanego do wdrożenia.

-

Część inwersji Inversion of Control (IoC) jest myląca; ponieważ inwersja jest terminem względnym. Najlepszym sposobem na zrozumienie IoC jest zapomnienie o tym słowie!

-

Przykłady

  • Obsługa zdarzeń. Event Managery (część do zrobienia) - Podnoszenie zdarzeń (część do zrobienia)
  • Interfejsy Klient Component (część do zrobienia) - Implementacja interfejsu Component (część do zrobienia)
  • Urządzenie xUnit. Setup i TearDown (część czynności do wykonania) - xUnit frameworki wywołuje Instalatora na początku, a TearDown na końcu (część do zrobienia)
  • Wzór szablonu metody projektowania. metoda szablonowa część czasu do zrobienia - prymitywna implementacja podklasy część czynności do wykonania
  • Metody kontenera DLL w modelu COM. DllMain, DllCanUnload itp. (Część czynności do wykonania) - COM / OS (część czynności do wykonania)
rpattabi
źródło
Jak mówisz Interfejsy. Klient składowy (część „kiedy to zrobić”) jako „kiedy” nie ma sensu, gdy używamy interfejsów (np. Wstrzykiwanie zależności), po prostu go wyodrębniamy i dajemy klientowi elastyczność w dodawaniu dowolnej implementacji, ale nie ma „kiedy” zaangażowany tam. Zgadzam się z „kiedy” w przypadku podnoszenia zdarzeń obsługi zdarzeń.
OldSchool
Przez „komponentowego klienta” miałem na myśli użytkownika / klienta interfejsu. Klient wie, „kiedy” uruchomić część „co zrobić”, czy intencją jest rozszerzenie funkcjonalności, czy nie.
rpattabi
Spójrz na ten wspaniały artykuł Martina Fowlera. Pokazuje, w jaki sposób interfejsy stanowią podstawową część inwersji kontroli: martinfowler.com/articles/injection.html#InversionOfControl
rpattabi
dwa pierwsze zdania są genialne. niesamowite !! Idealne rozdzielenie według czasu, kiedy i co robić !! nie wiem, dlaczego inne odpowiedzi są tak popularne. po prostu mówią kody bez żadnego zrozumienia.
Amir Ziarati,
2
Podoba mi się wyjaśnienie what-to-doiwhen-to-do
KimchiMan
164

Inwersja kontroli polega na oddzieleniu problemów.

Bez IoC : masz laptopa i przypadkowo zepsułeś ekran. Cholera, okazuje się, że ten sam model ekranu laptopa nie ma nigdzie na rynku. Więc utknąłeś.

Z IoC : masz komputer stacjonarny i przypadkowo zepsułeś ekran. Zauważysz, że możesz po prostu pobrać prawie każdy monitor stacjonarny z rynku i działa dobrze z twoim komputerem stacjonarnym.

W tym przypadku komputer pomyślnie wdraża IoC. Akceptuje różne typy monitorów, podczas gdy laptop nie, potrzebuje określonego ekranu, aby się naprawić.

Luo Jiong Hui
źródło
1
@Luo Jiong Hui Ładne wyjaśnienie.
Sachin
3
Większość wzorów projektowych, jeśli nie wszystkie, mają swoje odpowiedniki w naszym codziennym życiu, które tak dobrze widzimy i rozumiemy. Najbardziej skutecznym sposobem zrozumienia wzoru jest poznanie ich codziennych odpowiedników. I wierzę, że jest ich wiele.
Luo Jiong Hui
6
Niepoprawna odpowiedź. Wyjaśniasz zastrzyk zależności, a nie IoC. Zobacz komentarz Rogério do tej odpowiedzi powyżej
MickyD
2
Zgadzam się. To jest DI, a nie IoC. Nadal dostaje opinię, ponieważ jest to proste podejście, ale pomaga poszerzyć zrozumienie tematu.
Mär
Wyjaśnia zastrzyk zależności. Nie Ioc. Ale miłe i jasne wytłumaczenie.
Chamin Wickramarathna,
120

Inversion of Control ((IoC)) polega na uzyskaniu wolności (bierzesz ślub, straciłeś wolność i jesteś kontrolowany. Rozwiedliście się, właśnie wdrożyliście Inversion of Control. To właśnie nazwaliśmy „oddzielonym”. Dobry system komputerowy zniechęca do bardzo bliskich relacji.) większa elastyczność (kuchnia w biurze serwuje tylko czystą wodę z kranu, co jest twoim jedynym wyborem, gdy chcesz się napić. Twój szef wdrożył Inversion of Control, konfigurując nowy ekspres do kawy. Teraz otrzymujesz elastyczność wyboru wody z kranu lub kawy) i mniejsza zależność (Twój partner ma pracę, nie masz pracy, jesteś zależny finansowo od partnera, więc jesteś pod kontrolą. Znajdujesz pracę, wdrożyłeś Inwersję Kontroli. Dobry system komputerowy zachęca do zależności.)

Kiedy korzystasz z komputera stacjonarnego, jesteś slave (lub powiedzmy, kontrolujesz). Musisz usiąść przed ekranem i spojrzeć na niego. Używanie klawiatury do pisania i nawigacja za pomocą myszy. Źle napisane oprogramowanie może cię jeszcze bardziej zniewolić. Jeśli zastąpisz komputer stacjonarny laptopem, masz nieco odwróconą kontrolę. Możesz go łatwo zabrać i poruszać się. Teraz możesz kontrolować swoje położenie za pomocą komputera, zamiast sterować nim.

Dzięki wdrożeniu Inversion of Control konsument oprogramowania / obiektu uzyskuje większą kontrolę / opcje nad oprogramowaniem / obiektami, zamiast być kontrolowanym lub mając mniej opcji.

Mając na uwadze powyższe pomysły. Nadal brakuje nam kluczowej części IoC. W scenariuszu IoC konsument oprogramowania / obiektu stanowi wyrafinowane środowisko. Oznacza to, że utworzony kod nie jest wywoływany przez Ciebie. Wyjaśnijmy teraz, dlaczego ten sposób działa lepiej dla aplikacji internetowej.

Załóżmy, że Twój kod to grupa pracowników. Muszą zbudować samochód. Pracownicy ci potrzebują miejsca i narzędzi (ramy oprogramowania) do budowy samochodu. Tradycyjne ramy oprogramowanie będzie jak garaż z wielu narzędzi. Dlatego pracownicy muszą sami opracować plan i użyć narzędzi do budowy samochodu. Budowa samochodu nie jest łatwym przedsięwzięciem, pracownikom naprawdę ciężko będzie odpowiednio zaplanować i współpracować. nowoczesnyramy oprogramowania będą przypominały nowoczesną fabrykę samochodów ze wszystkimi udogodnieniami i menedżerami. Pracownicy nie muszą tworzyć żadnego planu, menedżerowie (część frameworka, są najmądrzejszymi ludźmi i stworzyli najbardziej wyrafinowany plan) pomogą koordynować, aby pracownicy wiedzieli, kiedy wykonać swoją pracę (framework nazywa Twój kod). Pracownicy muszą być na tyle elastyczni, aby korzystać z narzędzi, które dają im menedżerowie (za pomocą wstrzykiwania zależności).

Chociaż pracownicy przekazują kontrolę nad zarządzaniem projektem na najwyższym poziomie menedżerom (struktura). Ale dobrze jest, aby niektórzy profesjonaliści ci pomogli. Z tego właśnie pochodzi koncepcja Internetu Rzeczy.

Nowoczesne aplikacje internetowe z architekturą MVC zależą od frameworka, który wykonuje routing URL i umieszcza Kontrolery na miejscu, aby framewor mógł zadzwonić.

Wstrzykiwanie zależności i odwracanie kontroli są powiązane. Wstrzykiwanie zależności odbywa się na poziomie mikro , a odwrócenie kontroli na poziomie makro . Musisz zjeść każdy kęs (implement DI), aby zakończyć posiłek (implement IoC).

Luo Jiong Hui
źródło
21
Głosowałem za porównaniem DI do małżeństwa i IoC do rozwodu.
Marek Bar
„Chociaż pracownicy przekazują kontrolę nad zarządzaniem projektem na najwyższym szczeblu menedżerom (ramy). Dobrze jest jednak, aby niektórzy profesjonaliści ci pomogli. To jest koncepcja IoC, z której naprawdę pochodzą.” - Po pierwsze kontrola jest z menedżerem. Czy możesz wyjaśnić, jak ta kontrola jest odwrócona? Z pomocą profesjonalistów (jakiego rodzaju profesjonalisty)? W jaki sposób ?
Istiaque Ahmed
@Istiaque Ahmed, w porównaniu do garażu, w którym pracownicy mają pełną kontrolę nad wszystkim, menedżerowie w nowoczesnej fabryce samochodów kontrolują produkcję. Więc teraz pracownicy są kontrolowani zamiast kontrolować. Należy pamiętać, że menedżerowie w tym kontekście są częścią nowoczesnej fabryki samochodów, a nie częścią pracowników. Specjaliści to menedżerowie, którzy są profesjonalni w planowaniu i produkcji samochodów.
Luo Jiong Hui,
2
Wiadomość dla osób pozostających w związku małżeńskim: nie rozwodź się teraz, twoje zajęcia dla dzieci mogą również wdrażać IoC.
Julian
Tak, to właśnie moja wizja małżeństwa również IoC
balron
94

Przed użyciem Inversion of Control powinieneś być świadomy faktu, że ma to swoje zalety i wady i powinieneś wiedzieć, dlaczego go używasz, jeśli to robisz.

Plusy:

  • Twój kod zostaje oddzielony, dzięki czemu możesz łatwo wymieniać implementacje interfejsu z alternatywnymi implementacjami
  • Jest to silny motywator do kodowania interfejsów zamiast implementacji
  • Bardzo łatwo jest napisać testy jednostkowe dla twojego kodu, ponieważ zależy to wyłącznie od obiektów, które akceptuje w swoim konstruktorze / ustawieniach i możesz je łatwo zainicjować za pomocą odpowiednich obiektów w izolacji.

Cons:

  • IoC nie tylko odwraca przepływ sterowania w twoim programie, ale także znacznie go zasłania. Oznacza to, że nie możesz już po prostu czytać kodu i przeskakiwać z jednego miejsca na drugie, ponieważ połączenia, które normalnie byłyby w twoim kodzie, nie są już w nim kodowane. Zamiast tego jest w plikach konfiguracyjnych XML lub adnotacjach oraz w kodzie kontenera IoC, który interpretuje te metadane.
  • Pojawia się nowa klasa błędów, w których źle konfigurujesz XML lub adnotacje, i możesz spędzić dużo czasu, aby dowiedzieć się, dlaczego Twój kontener IoC wstrzykuje odwołanie zerowe do jednego z twoich obiektów pod pewnymi warunkami.

Osobiście widzę mocne strony IoC i bardzo mi się podobają, ale staram się unikać IoC, gdy tylko jest to możliwe, ponieważ zamienia twoje oprogramowanie w zbiór klas, które nie stanowią już „prawdziwego” programu, ale po prostu coś, co musi połączyć Konfiguracja XML lub metadane adnotacji i rozpadałyby się (i rozpadały) bez niego.

ahe
źródło
3
Pierwszy oszust jest niepoprawny. Idealnie powinno być tylko 1 użycie kontenera IOC w twoim kodzie, i to jest twoja główna metoda. Wszystko inne powinno się stamtąd
spływać
23
Myślę, że chodzi mu o to, że nie możesz po prostu przeczytać: myService.DoSomething () i przejść do definicji DoSomething, ponieważ w IoC myService jest tylko interfejsem, a faktyczna implementacja jest dla Ciebie nieznana, chyba że przejrzysz to w plikach konfiguracyjnych xml lub głównej metodzie, w której twój ioc dostaje konfigurację.
chrismay
7
W tym pomaga Resharper - „kliknij idź do implementacji” w stosunku do interfejsu. Unikanie IoC (a ściślej DI z twojego przykładu) prawdopodobnie oznacza również, że nie
testujesz
10
Re: zamienia twoje oprogramowanie w zbiór klas, które nie stanowią już „prawdziwego” programu, ale po prostu coś, co musi zostać połączone przez konfigurację XML lub metadane adnotacji i rozpadałoby się (i rozpadało) bez niego - myślę, że to jest bardzo mylące. To samo można powiedzieć o każdym programie napisanym na frameworku. Różnica w stosunku do dobrego kontenera IoC polega na tym, że powinieneś być w stanie, jeśli twój program jest dobrze zaprojektowany i napisany, wyjąć go i zainstalować w innym z minimalnymi zmianami w kodzie lub całkowicie wyrzucić IoC i ręcznie konstruować obiekty .
The Awnry Bear
7
Dobrze widzieć taką odpowiedź w świecie rzeczywistym! Myślę, że istnieje mnóstwo doświadczonych programistów, znających się na projektowaniu obiektowym i praktykach TDD, korzystających już z interfejsów, wzorów fabrycznych, modeli sterowanych zdarzeniami i kpowania tam, gdzie ma to sens, zanim wymyślono to modne hasło „IoC”. Niestety, zbyt wielu programistów / „architektów” twierdzi, że postępuje źle, jeśli nie używasz preferowanych przez siebie frameworków. Wolę lepszy projekt, wykorzystanie wbudowanych pojęć i narzędzi językowych, aby osiągnąć ten sam cel przy ułamku złożoności, tj. Bez „mętnienia” implementacji, jak mówisz :-)
Tony Wall
68
  1. Artykuł w Wikipedii . Dla mnie odwrócenie kontroli zamienia Twój sekwencyjnie napisany kod i przekształca go w strukturę delegacji. Zamiast programu, który wyraźnie kontroluje wszystko, program tworzy klasę lub bibliotekę z pewnymi funkcjami, które mają być wywoływane, gdy pewne rzeczy się zdarzają.

  2. Rozwiązuje duplikację kodu. Na przykład w dawnych czasach ręcznie pisałeś własną pętlę zdarzeń, odpytując biblioteki systemowe pod kątem nowych zdarzeń. W dzisiejszych czasach większość współczesnych interfejsów API po prostu informuje biblioteki systemowe, jakie zdarzenia są zainteresowane, i informuje o tym, kiedy się one zdarzają.

  3. Odwrócenie kontroli jest praktycznym sposobem na ograniczenie duplikacji kodu, a jeśli odkryjesz, że kopiujesz całą metodę i zmieniasz tylko niewielką część kodu, możesz rozważyć rozwiązanie problemu z odwróceniem kontroli. Odwrócenie kontroli jest łatwe w wielu językach dzięki koncepcji delegatów, interfejsów, a nawet surowych wskaźników funkcji.

    Nie jest właściwe stosowanie we wszystkich przypadkach, ponieważ przepływ programu może być trudniejszy do śledzenia, gdy jest napisany w ten sposób. Jest to przydatny sposób projektowania metod podczas pisania biblioteki, która będzie ponownie używana, ale powinna być używana oszczędnie w rdzeniu własnego programu, chyba że naprawdę rozwiązuje problem duplikacji kodu.

NilObject
źródło
37
Uważam, że ten artykuł w Wikipedii jest bardzo mylący i wymaga naprawy. Śmiej się na stronie dyskusji.
devios1,
Pisanie własnej pętli zdarzeń może nadal być odwróceniem kontroli, jeśli ta pętla zdarzeń zastąpi strukturę, a reszta kodu korzysta z zasady IoC, właśnie napisałeś własną strukturę. W rzeczywistości nie jest to zła rzecz, zwiększa czytelność za cenę tylko trochę więcej kodowania (nie to też, że zawsze jest odpowiednie).
lijat
45

Ale myślę, że musisz być bardzo ostrożny. Jeśli nadużyjesz tego wzorca, stworzysz bardzo skomplikowany projekt i jeszcze bardziej skomplikowany kod.

Jak w tym przykładzie z TextEditor: jeśli masz tylko jeden moduł sprawdzania pisowni, może nie jest tak naprawdę konieczne korzystanie z IoC? Chyba że musisz pisać testy jednostkowe lub coś ...

W każdym razie: bądź rozsądny. Wzory projektowe to dobre praktyki, ale nie należy ich głosić w Biblii. Nie przyklejaj go wszędzie.

Michał Sznajder
źródło
3
Skąd wiesz, że będziesz mieć tylko jeden moduł sprawdzania pisowni?
Śledź
@Trace Możesz na przykład wiedzieć, w jaki sposób program, który napiszesz, będzie używany. Jednak niektóre techniki, takie jak wstrzykiwanie zależności, są tak tanie, że rzadko istnieje powód, aby nie używać ich w takim przypadku.
lijat
44

IoC / DI dla mnie wypiera zależności do obiektów wywołujących. Super proste.

Nietechniczną odpowiedzią jest możliwość wymiany silnika w samochodzie tuż przed jego włączeniem. Jeśli wszystko się połączy (interfejs), jesteś dobry.

ferventcoder
źródło
44

Załóżmy, że jesteś przedmiotem. Idziesz do restauracji:

Bez IoC : prosisz o „jabłko” i zawsze podajesz jabłko, gdy prosisz o więcej.

Z IoC : możesz poprosić o „owoce”. Możesz otrzymać różne owoce za każdym razem, gdy je serwujesz. na przykład jabłko, pomarańcza lub arbuz.

Oczywiście IoC jest preferowane, gdy lubisz odmiany.

Luo Jiong Hui
źródło
26
  1. Odwrócenie kontroli jest wzorcem stosowanym do odsprzęgania komponentów i warstw w systemie. Wzorzec jest implementowany poprzez wstrzykiwanie zależności do komponentu podczas jego konstruowania. Zależności te są zwykle dostarczane jako interfejsy do dalszego oddzielania i wspierania testowalności. Kontenery IoC / DI, takie jak Castle Windsor, Unity są narzędziami (bibliotekami), których można używać do zapewniania IoC. Narzędzia te zapewniają rozszerzone funkcje wykraczające poza proste zarządzanie zależnościami, w tym okres istnienia, AOP / przechwytywanie, zasady itp.

  2. za. Zwalnia komponent z odpowiedzialności za zarządzanie jego zależnościami.
    b. Zapewnia możliwość zamiany implementacji zależności w różnych środowiskach.
    do. Umożliwia testowanie komponentu poprzez wyśmiewanie zależności.
    re. Zapewnia mechanizm udostępniania zasobów w całej aplikacji.

  3. za. Krytyczne przy tworzeniu testów opartych na testach. Bez IoC testowanie może być trudne, ponieważ testowane komponenty są silnie sprzężone z resztą systemu.
    b. Krytyczny przy opracowywaniu systemów modułowych. System modułowy to system, którego elementy można wymienić bez konieczności ponownej kompilacji.
    do. Krytyczne, jeśli istnieje wiele przekrojowych problemów, które należy rozwiązać, zwłaszcza w aplikacji korporacyjnej.

Glenn Block
źródło
2
W rzeczywistości IoC nie polega głównie na zarządzaniu zależnościami. Proszę zobaczyć martinfowler.com/articles/injection.html#InversionOfControl W szczególności zwróć uwagę na część zatytułowaną „Inwersja kontroli jest zbyt ogólnym terminem, dlatego ludzie uważają, że jest mylący. W wyniku wielu dyskusji z różnymi zwolennikami IoC, my ustalono na nazwę Dependency Injection ".
Rogério,
26

Odpowiadając tylko na pierwszą część. Co to jest?

Inwersja kontroli (IoC) oznacza tworzenie instancji zależności najpierw i drugiej instancji klasy (opcjonalnie wstrzykiwanie ich przez konstruktor), zamiast tworzenia instancji klasy najpierw, a następnie instancji klasy tworzącej instancje zależności. Tak więc odwrócenie sterowania odwraca się przepływ sterowania programem. Zamiast z odbierającym kontrolującego ten przepływ sterowania (podczas tworzenia zależnościami), przy czym rozmówca kontroluje przepływ kontroli programu .

użytkownik2330678
źródło
Nie chodzi o tworzenie klas ani obiektów, sprawdź to martinfowler.com/articles/injection.html#InversionOfControl
Raghvendra Singh
22

Spiszę moje proste zrozumienie tych dwóch terminów:

For quick understanding just read examples*

Wstrzykiwanie zależności (DI):
Wstrzykiwanie zależności zwykle oznacza przekazanie obiektu, od którego zależy metoda, jako parametru do metody, zamiast tworzenia metody zależnej przez metodę .
W praktyce oznacza to, że metoda nie zależy bezpośrednio od konkretnego wdrożenia; każda implementacja spełniająca wymagania może zostać przekazana jako parametr.

Dzięki tym obiektom powiedz im o swoich zależnościach. A wiosna czyni go dostępnym.
Prowadzi to do luźno powiązanego tworzenia aplikacji.

Quick Example:EMPLOYEE OBJECT WHEN CREATED,
              IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
   (if address is defines as dependency by Employee object)

Kontener Inversion of Control (IoC):
jest to wspólna cecha frameworków, MKOl zarządza obiektami Java
- od instancji do zniszczenia poprzez BeanFactory.
Komponenty Java, które są tworzone przez kontener IoC, nazywane są fasolami, a kontener IoC zarządza zakresem komponentu bean, zdarzeniami cyklu życia oraz wszelkimi funkcjami AOP, dla których został skonfigurowany i zakodowany.

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.

Implementując Inversion of Control, użytkownik oprogramowania / obiektu uzyskuje więcej kontroli / opcji nad oprogramowaniem / obiektami, zamiast być kontrolowanym lub mając mniej opcji.

Odwrócenie kontroli jako wytyczne projektowe służy następującym celom:

Występuje oddzielenie wykonania określonego zadania od realizacji.
Każdy moduł może skupić się na tym, do czego jest przeznaczony.
Moduły nie przyjmują żadnych założeń dotyczących tego, co robią inne systemy, ale polegają na swoich umowach.
Zastąpienie modułów nie ma wpływu ubocznego na inne moduły.
Będę tutaj utrzymywał abstrakcję. Możesz odwiedzić poniższe linki, aby uzyskać szczegółowe informacje na ten temat.
Dobra lektura z przykładem

Szczegółowe wyjaśnienie

VdeX
źródło
17

Zgadzam się z NilObject , ale chciałbym dodać do tego:

jeśli okaże się, że kopiujesz całą metodę i zmieniasz tylko niewielki fragment kodu, możesz rozważyć zajęcie się tym z odwróceniem kontroli

Jeśli kopiujesz i wklejasz kod, prawie zawsze robisz coś złego. Skodyfikowane jako zasada projektowania Raz i tylko raz .

Peter Burns
źródło
17

Na przykład zadaniem nr 1 jest utworzenie obiektu. Bez koncepcji IOC zadanie nr 1 powinno być wykonane przez programistę, ale w przypadku koncepcji IOC zadanie nr 1 byłoby wykonane przez kontener.

W skrócie Kontrola zostaje odwrócona z Programmera do kontenera. Nazywa się to więc odwróceniem kontroli.

Znalazłem jeden dobry przykład tutaj .

gogs
źródło
Kontener jest koncepcją w IoC, w której model obiektowy, w tym zależności (relacje między obiektem „użytkownika” i „używanego” obiektu) i instancje obiektów, rezydują i są zarządzane - np. Zawarte. Kontener jest zwykle dostarczany przez platformę IoC, taką jak Spring. Pomyśl o tym jak o repozytorium środowiska wykonawczego dla obiektów tworzących twoją aplikację.
The Awnry Bear
17

Powiedzmy, że umawiamy się na spotkanie w jakimś hotelu.

Wiele osób, wiele karafek wody, wiele plastikowych kubków.

Kiedy ktoś chce się napić, napełnia kubek, pije i rzuca kubek na podłogę.

Po godzinie czy coś mamy podłogę pokrytą plastikowymi kubkami i wodą.

Pozwól odwrócić kontrolę.

To samo spotkanie w tym samym miejscu, ale zamiast plastikowych kubków mamy kelnera z jednym szklanym kubkiem (Singleton)

i ona cały czas oferuje gościom picie.

Kiedy ktoś chce się napić, wychodzi ze szklanki kelnera, pije i oddaje kelnerowi.

Pomijając kwestię higienicznej, ostatniej formy kontroli procesu picia, jest on znacznie bardziej skuteczny i ekonomiczny.

I dokładnie to robi Spring (inny kontener IoC, na przykład: Guice). Zamiast zezwalać aplikacji na tworzenie potrzebnych informacji za pomocą nowego słowa kluczowego (biorąc plastikowy kubek), pojemnik Spring IoC cały czas oferuje stosowanie tego samego wystąpienia (singletonu) potrzebnego obiektu (szklanka wody).

Pomyśl o sobie jako o organizatorze takiego spotkania. Potrzebujesz sposobu na przesłanie tego do administracji hotelu

członkowie spotkania będą potrzebować szklanki wody, ale nie bułki z masłem.

Przykład:-

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

}

Przydatne linki:-

Jainendra
źródło
nie są obiektami typu statycznego singletony?
Gokigooooks
16

Wydaje się, że najbardziej mylącą rzeczą w „IoC” akronimie i nazwie, dla której on oznacza, jest to, że nazwa jest zbyt czarująca - nazwa prawie szumowa.

Czy naprawdę potrzebujemy nazwy, za pomocą której można opisać różnicę między programowaniem proceduralnym a programowaniem zdarzeń? OK, jeśli musimy, ale czy musimy wybrać zupełnie nową nazwę „większe niż życie”, która dezorientuje bardziej niż rozwiązuje?

email.privacy
źródło
1
IoC! = Sterowane zdarzeniem. Podobieństwa (w niektórych przypadkach pokrywają się), ale zasadniczo nie są one tym samym paradygmatem.
The Awnry Bear
Dobre pytanie. Programowanie oparte na zdarzeniach jest z pewnością IoC. Piszemy moduły obsługi zdarzeń, które są wywoływane z pętli zdarzeń. Ale IoC jest bardziej ogólną koncepcją niż programowanie oparte na zdarzeniach. Jeśli przesłonisz metodę w podklasie, jest to również rodzaj IoC. Napisz kod, który zostanie wywołany, gdy zostanie użyte odpowiednie odwołanie (instancja).
vi.su.
15

Odwrócenie kontroli ma miejsce, gdy idziesz do sklepu spożywczego, a twoja żona daje ci listę produktów do kupienia.

W zakresie programowania przekazała funkcję zwrotną getProductList()do funkcji, którą wykonujesz - doShopping().

Pozwala użytkownikowi funkcji zdefiniować niektóre jego części, czyniąc ją bardziej elastyczną.

Siergiej Ostrowski
źródło
5
Moja żona zwykle robi u mnie zakupy, ale zgadzam się z tym stwierdzeniem.
ha9u63ar
1
@ ha9u63ar Twoja żona robi z tobą zakupy? To się nazywa agregacja.
Julian
2
Jeśli ona również daje pieniądze, nazywa się to DI.
San
1
Słowo Inwersja - do góry nogami - pochodzi od tego, że kiedy dzwoni żona getProductList(), musisz znaleźć źródło pieniędzy, co oznacza, że ​​kontrola jest po twojej stronie. W przypadku inwersji będzie kontrolowała, co oznacza, że ​​pieniądze, które zapewni ona na zakup.
San
13

Znalazłem tutaj bardzo jasny przykład , który wyjaśnia, w jaki sposób „sterowanie jest odwrócone”.

Kod klasyczny (bez wstrzykiwania zależności)

Oto, w jaki sposób kod nieobsługujący DI będzie działać z grubsza:

  • Aplikacja wymaga Foo (np. Kontrolera), więc:
  • Aplikacja tworzy Foo
  • Aplikacja wywołuje Foo
    • Foo potrzebuje paska (np. Usługi), więc:
    • Foo tworzy Bar
    • Foo nazywa się Bar
      • Bar potrzebuje Bim (usługa, repozytorium,…), więc:
      • Bar tworzy Bim
      • Bar coś robi

Za pomocą wstrzykiwania zależności

Oto jak z grubsza działa kod korzystający z DI:

  • Aplikacja potrzebuje Foo, która potrzebuje paska, który potrzebuje Bim, więc:
  • Aplikacja tworzy Bim
  • Aplikacja tworzy Bar i nadaje mu Bim
  • Aplikacja tworzy Foo i daje mu pasek
  • Aplikacja wywołuje Foo
    • Foo nazywa się Bar
      • Bar coś robi

Kontrola zależności jest odwrócona z jednej osoby wzywającej na drugą.

Jakie problemy rozwiązuje?

Wstrzykiwanie zależności ułatwia wymianę z różnymi implementacjami wstrzykiwanych klas. Podczas testowania jednostkowego można wstrzykiwać fałszywą implementację, co znacznie ułatwia testowanie.

Przykład: Załóżmy, że Twoja aplikacja przechowuje plik przesłany przez użytkownika na Dysku Google, z DI kod kontrolera może wyglądać następująco:

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) {}
}

Gdy zmienią się twoje wymagania, powiedz, zamiast GoogleDrive zostaniesz poproszony o użycie Dropbox. Musisz tylko napisać implementację Dropbox dla StorageServiceInterface. Nie wprowadzasz żadnych zmian w kontrolerze, dopóki implementacja Dropbox przestrzega interfejsu StorageServiceInterface.

Podczas testowania można utworzyć próbkę dla StorageServiceInterface za pomocą fikcyjnej implementacji, w której wszystkie metody zwracają wartość null (lub dowolną wstępnie zdefiniowaną wartość zgodnie z wymaganiami dotyczącymi testowania).

Zamiast tego, jeśli masz klasę kontrolera do zbudowania obiektu pamięci za pomocą newsłowa kluczowego w ten sposób:

class SomeController
{
    private $storage;

    function __construct()
    {
        $this->storage = new GoogleDriveService();
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

Jeśli chcesz zmienić za pomocą implementacji Dropbox, musisz zastąpić wszystkie wiersze, w których newbudowany jest obiekt GoogleDriveService i użyć DropboxService. Poza tym podczas testowania klasy SomeController konstruktor zawsze oczekuje klasy GoogleDriveService i uruchamiane są rzeczywiste metody tej klasy.

Kiedy jest to właściwe, a kiedy nie? Moim zdaniem używasz DI, jeśli uważasz, że istnieją (lub mogą być) alternatywne implementacje klasy.

Raghavendra N.
źródło
To powinna być najbardziej poprawna odpowiedź, ponieważ jedyna wyjaśnia, w jaki sposób „sterowanie” jest odwrócone.
Yarimadam
najlepsze jak dotąd wyjaśnienie
Ali80
12

Bardzo proste pisemne wyjaśnienie można znaleźć tutaj

http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html

To mówi -

„Każda nietrywialna aplikacja składa się z dwóch lub więcej klas, które współpracują ze sobą w celu wykonania logiki biznesowej. Tradycyjnie każdy obiekt jest odpowiedzialny za uzyskanie własnych odniesień do obiektów, z którymi współpracuje (jego zależności). obiekty otrzymują swoje zależności w czasie tworzenia przez jakiś zewnętrzny byt, który koordynuje każdy obiekt w systemie. Innymi słowy, zależności są wstrzykiwane do obiektów. ”

agaase
źródło
12

Odwrócenie kontroli jest ogólną zasadą, podczas gdy funkcja Dependency Injection realizuje tę zasadę jako wzorzec projektowy do budowy grafów obiektowych (tj. Konfiguracja kontroluje, w jaki sposób obiekty się do siebie odnoszą, a nie sam obiekt kontroluje sposób uzyskania odniesienia do innego obiektu).

Patrząc na odwrócenie kontroli jako wzorzec projektowy, musimy spojrzeć na to, co odwracamy. Wstrzykiwanie zależności odwraca kontrolę nad konstruowaniem wykresu obiektów. Odwrócona kontrola, jeśli jest to powiedziane dla laika, oznacza zmianę przepływu kontroli w programie. Na przykład. W tradycyjnej samodzielnej aplikacji mamy główną metodę, z której kontrola jest przekazywana do innych bibliotek stron trzecich (w przypadku, gdy korzystaliśmy z funkcji biblioteki strony trzeciej), ale poprzez odwrócenie kontroli kontrola jest przenoszona z kodu biblioteki strony trzeciej do naszego kodu , ponieważ korzystamy z usług biblioteki zewnętrznej. Istnieją jednak inne aspekty, które należy odwrócić w programie - np. Wywołanie metod i wątków w celu wykonania kodu.

Dla zainteresowanych bardziej dogłębnie na temat Inwersji Kontroli opublikowano artykuł przedstawiający pełniejszy obraz Inwersji Kontroli jako wzorca projektowego (OfficeFloor: używanie wzorców biurowych do ulepszania projektowania oprogramowania http://doi.acm.org/10.1145/ 2739011.2739013 z bezpłatną kopią dostępną do pobrania ze strony http://www.officefloor.net/about.html ).

Zidentyfikowano następujący związek:

Odwrócenie kontroli (dla metod) = wtrysk zależny (stan) + wtrysk kontynuacyjny + wtrysk nici

Podsumowanie powyższej zależności dla Inversion of Control dostępne - http://dzone.com/articles/inversion-of-coupling-control

Daniel Sagenschneider
źródło
To bardzo jasna odpowiedź. Dziękuję za wyjaśnienie.
KunYu Tsai,
11

IoC polega na odwróceniu relacji między twoim kodem a kodem strony trzeciej (biblioteka / framework):

  • Podczas normalnego programowania s / w piszesz metodę main () i wywołujesz metody „biblioteczne”. Masz kontrolę :)
  • W IoC „framework” kontroluje main () i wywołuje twoje metody. Ramowa jest pod kontrolą :(

DI (Dependency Injection) dotyczy przepływu kontroli w aplikacji. Tradycyjna aplikacja komputerowa miała przepływ sterowania z aplikacji (metoda main ()) do innych wywołań metod bibliotecznych, ale w przypadku sterowania DI przepływ jest odwrócony, dzięki czemu framework zajmuje się uruchamianiem aplikacji, inicjowaniem jej i wywoływaniem metod w razie potrzeby.

W końcu zawsze wygrywasz :)

Khan
źródło
10

Podoba mi się to wyjaśnienie: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/

Zaczyna się prosty i pokazuje również przykłady kodu.

wprowadź opis zdjęcia tutaj

Konsument, X, potrzebuje konsumowanej klasy Y, aby coś osiągnąć. To wszystko jest dobre i naturalne, ale czy X naprawdę musi wiedzieć, że używa Y?

Czy nie wystarczy, że X wie, że używa czegoś, co ma zachowanie, metody, właściwości itp. Y, nie wiedząc, kto faktycznie wdraża to zachowanie?

Wyodrębniając abstrakcyjną definicję zachowania używanego przez X w Y, zilustrowaną jako I poniżej, i pozwalając konsumentowi X na użycie tego wystąpienia zamiast Y, może on nadal robić to, co robi, bez konieczności poznawania specyfiki Y.

wprowadź opis zdjęcia tutaj

Na powyższej ilustracji Y implementuje I, a X używa instancji I. Chociaż jest całkiem możliwe, że X nadal używa Y, interesujące jest to, że X o tym nie wie. Po prostu wie, że używa czegoś, co implementuje I.

Przeczytaj artykuł, aby uzyskać dodatkowe informacje i opis korzyści, takich jak:

  • X nie jest już zależny od Y.
  • Bardziej elastyczna implementacja może zostać podjęta w czasie wykonywania
  • Izolacja jednostki kodu, łatwiejsze testowanie

...

DDan
źródło
Link jest bardzo pomocny. Naprawdę dziękuję :)
M Fuat NUROĞLU
10

Rozumiem, że odpowiedź została już tutaj podana. Ale nadal uważam, że niektóre podstawowe informacje o odwróceniu kontroli muszą być tutaj omówione szczegółowo dla przyszłych czytelników.

Inwersja kontroli (IoC) została zbudowana na bardzo prostej zasadzie zwanej Hollywood Principle . I mówi, że

Nie dzwoń do nas, my zadzwonimy do ciebie

Oznacza to, że nie idź do Hollywood, aby spełnić swoje marzenie, a jeśli jesteś godny, Hollywood cię odnajdzie i spełni twoje marzenie. Prawie odwrócony, co?

Teraz, gdy dyskutujemy o zasadzie IoC, zapominamy o Hollywood. Dla IoC musi być trzy element, Hollywood, ty i zadanie takie jak spełnienie twojego marzenia.

W naszym świecie programowania, Hollywood stanowią ogólne ramy (może być napisany przez ciebie lub kogoś innego), Państwo reprezentują kod użytkownika został zapisany i zadanie reprezentowania rzeczą, którą chcesz osiągnąć w kodzie. Teraz nigdy nie zaczynasz samodzielnie uruchamiać swojego zadania, nie w IoC! Zamiast tego zaprojektowałeś wszystko w taki sposób, że twoje środowisko uruchomi za ciebie zadanie. W ten sposób zbudowałeś platformę wielokrotnego użytku, która może uczynić kogoś bohaterem lub innym złoczyńcą. Ale ten szkielet jest zawsze odpowiedzialny, wie, kiedy kogoś wybrać, i że ktoś wie tylko, czym chce być.

Podano by tutaj prawdziwy przykład z życia. Załóżmy, że chcesz opracować aplikację internetową. Tak więc tworzysz strukturę, która będzie obsługiwać wszystkie typowe rzeczy, które aplikacja internetowa powinna obsługiwać, takie jak obsługa żądania http, tworzenie menu aplikacji, serwowanie stron, zarządzanie plikami cookie, wyzwalanie zdarzeń itp

A potem zostawiasz pewne haczyki w swoim frameworku, w których możesz umieścić kolejne kody w celu wygenerowania niestandardowego menu, stron, plików cookie lub rejestrowania niektórych zdarzeń użytkownika itp. Na każde żądanie przeglądarki, twoja struktura uruchomi się i wykona twoje niestandardowe kody, jeśli zostanie zaczepiona, a następnie odeśle ją do przeglądarki.

Pomysł jest więc bardzo prosty. Zamiast tworzyć aplikację użytkownika, która będzie kontrolować wszystko, najpierw stworzysz platformę wielokrotnego użytku, która będzie kontrolować wszystko, a następnie napiszesz niestandardowe kody i podpisz je do ramy, aby wykonać je na czas.

Laravel i EJB są przykładami takich ram.

Odniesienie:

https://martinfowler.com/bliki/InversionOfControl.html

https://en.wikipedia.org/wiki/Inversion_of_control

Abdullah Al Farooq
źródło
1
Najbardziej odpowiednia odpowiedź, którą znalazłem tutaj.
blueray
8

Programowanie mówienia

IoC w prostych słowach: jest to użycie interfejsu jako sposobu na określone coś (takie pole lub parametr) jako symbol wieloznaczny, który może być używany przez niektóre klasy. Pozwala to na ponowne użycie kodu.

Załóżmy na przykład, że mamy dwie klasy: Pies i Kot . Oba mają te same cechy / stany: wiek, rozmiar, wagę. Zamiast tworzyć klasę usług o nazwie DogService i CatService , mogę utworzyć jedną o nazwie AnimalService, która pozwala korzystać z Dog i Cat tylko wtedy, gdy używają interfejsu IAnimal .

Jednak pragmatycznie rzecz biorąc, ma pewne zacofanie.

a) Większość programistów nie wie, jak z niego korzystać . Na przykład mogę utworzyć klasę o nazwie Klient i mogę automatycznie (za pomocą narzędzi IDE) utworzyć interfejs o nazwie ICustomer . Dlatego nierzadko znajduje się folder wypełniony klasami i interfejsami, bez względu na to, czy interfejsy zostaną ponownie użyte, czy nie. Nazywa się BLOATED. Niektórzy ludzie mogą argumentować, że „możemy być w przyszłości, moglibyśmy z niego skorzystać”. : - |

b) Ma pewne ograniczenia. Na przykład, porozmawiajmy o sprawie Dog and Cat i chcę dodać nową usługę (funkcjonalność) tylko dla psów. Powiedzmy, że chcę obliczyć liczbę dni, które muszę wyszkolić psa ( trainDays()), ponieważ kot jest bezużyteczny, kotów nie można trenować (żartuję).

b.1) Jeśli dodam trainDays()do usługi AnimalService Service, działa ona również z kotami i wcale nie jest ważna.

b.2) Mogę dodać warunek, w trainDays()którym ocenia, która klasa jest używana. Ale całkowicie przełamie IoC.

b.3) Mogę stworzyć nową klasę usług o nazwie DogService tylko dla nowej funkcjonalności. Ale zwiększy to łatwość konserwacji kodu, ponieważ będziemy mieć dwie klasy usług (o podobnej funkcjonalności) dla Dog i jest źle.

magallanes
źródło
O rozdętych klasach / interfejsach: Nie zawsze musisz ponownie używać każdego interfejsu. Czasami sensowne jest podzielenie dużego interfejsu na wiele mniejszych, aby zobaczyć jego funkcjonalne granice. Mniejsze interfejsy są również łatwiejsze do ponownego wykorzystania w innych implementacjach. Zachęca również do kodowania interfejsu, gdziekolwiek ma to sens. Rozważ „Segregację interfejsu”. Tylko dlatego, że używasz interfejsu, nie oznacza, że ​​jesteś oddzielony. Pojedynczy interfejs tłuszczu jest bezużyteczny. - Tylko moje 2 centy :)
MK
7

Przeczytałem wiele odpowiedzi na ten temat, ale jeśli ktoś nadal jest zdezorientowany i potrzebuje dodatkowo ultra „laikańskiego terminu”, aby wyjaśnić IoC, oto moje zdanie:

Wyobraź sobie, że rodzic i dziecko rozmawiają ze sobą.

Bez IoC:

* Rodzic : Możesz mówić tylko wtedy, gdy zadam ci pytania, i możesz działać tylko wtedy, gdy udzielę ci pozwolenia.

Rodzic : Oznacza to, że nie możesz mnie zapytać, czy możesz jeść, bawić się, iść do łazienki, a nawet spać, jeśli cię nie zapytam.

Rodzic : Czy chcesz jeść?

Dziecko : Nie.

Rodzic : Dobra, wrócę. Zaczekaj na mnie.

Dziecko : (chce się bawić, ale ponieważ rodzic nie ma pytania, dziecko nie może nic zrobić).

Po upływie 1 godziny...

Rodzic : wróciłem. Chcesz zagrać?

Dziecko : Tak.

Rodzic : zezwolenie przyznane.

Dziecko : (w końcu jest w stanie grać).

Ten prosty scenariusz wyjaśnia, że ​​sterowanie jest wyśrodkowane na obiekcie nadrzędnym. Wolność dziecka jest ograniczona i w dużej mierze zależy od pytania rodzica. Dziecko może mówić TYLKO, gdy zostanie o to poproszony, i może działać TYLKO , gdy uzyska zgodę.

Z IoC:

Dziecko ma teraz możliwość zadawania pytań, a rodzic może odpowiedzieć odpowiedziami i uprawnieniami. Oznacza to po prostu, że sterowanie jest odwrócone! Dziecko może teraz zadawać pytania w dowolnym momencie i chociaż nadal istnieje zależność od rodzica w zakresie uprawnień, nie jest on zależny od sposobu mówienia / zadawania pytań.

Z technologicznego punktu widzenia jest to bardzo podobne do interakcji między konsolą / powłoką / cmd a GUI. (Która jest odpowiedzią Marka Harrisona powyżej najwyższej odpowiedzi nr 2). W konsoli jesteś zależny od tego, o co Cię pyta / wyświetlasz i nie możesz przejść do innych menu i funkcji, nie odpowiadając najpierw na pytanie; po ścisłym sekwencyjnym przepływie. (programowo jest to jak pętla metody / funkcji). Jednak w przypadku GUI menu i funkcje są rozmieszczone, a użytkownik może wybrać wszystko, czego potrzebuje, dzięki czemu ma większą kontrolę i mniej ograniczeń. (programowo menu mają oddzwanianie po wybraniu i wykonywana jest akcja).

Reuben JaMes Aveño Gruta
źródło
6

Odwrócenie kontroli polega na przekazaniu kontroli z biblioteki do klienta. Ma to większy sens, gdy mówimy o kliencie, który wstrzykuje (przekazuje) wartość funkcji (wyrażenie lambda) do funkcji wyższego rzędu (funkcja biblioteki), która kontroluje (zmienia) zachowanie funkcji biblioteki. Klient lub środowisko, które wstrzykuje zależności bibliotek (które przenoszą zachowanie) do bibliotek, może być również uważane za IoC

Sergiu Starciuc
źródło
5

Ponieważ na pytanie jest już wiele odpowiedzi, ale żadna z nich nie pokazuje podziału terminu Inversion Control, widzę możliwość udzielenia bardziej zwięzłej i użytecznej odpowiedzi.

Inwersja kontroli to wzorzec, który implementuje zasadę inwersji zależności (DIP). DIP stwierdza, co następuje: 1. Moduły wysokiego poziomu nie powinny zależeć od modułów niskiego poziomu. Oba powinny zależeć od abstrakcji (np. Interfejsów). 2. Abstrakcje nie powinny zależeć od szczegółów. Szczegóły (konkretne wdrożenia) powinny zależeć od abstrakcji.

Istnieją trzy rodzaje odwrócenia kontroli:

Dostawcy odwracania interfejsu nie powinni definiować interfejsu. Zamiast tego konsument powinien zdefiniować interfejs, a dostawcy muszą go wdrożyć. Interfejs Inwersja pozwala wyeliminować konieczność modyfikacji konsumenta za każdym razem, gdy dodawany jest nowy dostawca.

Inwersja przepływu Zmienia kontrolę przepływu. Na przykład masz aplikację konsolową, w której prosiłeś o wprowadzenie wielu parametrów, a po każdym wprowadzonym parametrze musisz nacisnąć klawisz Enter. Możesz zastosować Flow Inversion i wdrożyć aplikację komputerową, w której użytkownik może wybrać sekwencję wprowadzania parametrów, użytkownik może edytować parametry, a na ostatnim etapie użytkownik musi nacisnąć klawisz Enter tylko raz.

Inwersja tworzenia Może być implementowana przez następujące wzorce: Wzorzec fabryczny, Lokalizator usług i Wstrzykiwanie zależności. Creation Inversion pomaga wyeliminować zależności między typami, przenosząc proces tworzenia obiektów zależności poza typ, który używa tych obiektów zależności. Dlaczego zależności są złe? Oto kilka przykładów: bezpośrednie utworzenie nowego obiektu w kodzie utrudnia testowanie; zmiana odnośników w złożeniach jest niemożliwa bez ponownej kompilacji (naruszenie zasady OCP); nie można łatwo zastąpić interfejsu użytkownika na pulpicie interfejsem użytkownika w sieci.

Vadim S.
źródło
3
  1. Więc numer 1 powyżej . Co to jest odwrócenie kontroli?

  2. Utrzymanie jest dla mnie najważniejszą rzeczą. Gwarantuje to, że używam interfejsów, aby dwie klasy nie były ze sobą bliskie.

Korzystając z pojemnika takiego jak Castle Windsor, rozwiązuje on problemy konserwacyjne jeszcze lepiej. Możliwość zamiany komponentu, który trafia do bazy danych, na taki, który używa trwałości opartej na plikach bez zmiany linii kodu jest niesamowita (zmiana konfiguracji, gotowe).

A kiedy przejdziesz do generycznych, staje się jeszcze lepszy. Wyobraź sobie, że masz wydawcę wiadomości, który odbiera rekordy i publikuje wiadomości. Nie obchodzi go, co publikuje, ale potrzebuje mapera, aby przenieść coś z rekordu do wiadomości.

public class MessagePublisher<RECORD,MESSAGE>
{
    public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
    {
      //setup
    }
}

Napisałem go raz, ale teraz mogę wstrzyknąć wiele typów do tego zestawu kodu, jeśli opublikuję różne typy wiadomości. Potrafię także pisać programy mapujące, które pobierają zapis tego samego typu i mapują je na różne wiadomości. Używanie DI z Generics dało mi możliwość napisania bardzo mało kodu do wykonania wielu zadań.

O tak, istnieją obawy dotyczące testowalności, ale są one drugorzędne w stosunku do korzyści płynących z IoC / DI.

Zdecydowanie kocham IoC / DI.

3) Staje się bardziej odpowiednie w momencie, gdy masz średniej wielkości projekt o nieco większej złożoności. Powiedziałbym, że staje się to właściwe, gdy tylko zaczniesz odczuwać ból.

ferventcoder
źródło
3

Tworzenie obiektu w klasie nazywa się ścisłym sprzężeniem, Spring usuwa tę zależność, postępując zgodnie z wzorcem projektowym (DI / IOC). W którym obiekcie klasy przekazywany jest konstruktor zamiast tworzenia w klasie. Ponadto podajemy zmienną referencyjną superklasy w konstruktorze, aby zdefiniować bardziej ogólną strukturę.

shA.t
źródło