Różnica między wtryskiem zależności (DI) a odwróceniem kontroli (IOC)

117

Widziałem wiele odniesień do Dependency Injection (DI) i Inversion Of Control (IOC), ale tak naprawdę nie wiem, czy jest między nimi różnica, czy nie.

Chciałbym zacząć korzystać z jednego lub obu z nich, ale jestem trochę zdezorientowany, jak się różnią.

komar
źródło
Odwrócenie kontroli zwykle odnosi się do „pojemników”, podczas gdy wstrzykiwanie zależności odnosi się do rzeczywistego wzorca. Ale idą w parze. Poleciłbym przeczytać artykuł Martina Fowlera, aby zrozumieć ten temat.
Ben Hoffstein,
Wstrzykiwanie zależności jest rzeczą, którą się robi, co prowadzi do struktury poleceń o nazwie Inwersja kontroli. Są z natury powiązane.
2
DI jest formą IoC, w tej odpowiedzi
2
Powiedziałbym, że DI jest szczególnym przypadkiem MKOl. Tradycyjne sterowanie przechodzi do modułu-> moduł żądania od menedżera modułów, w DI jest odwrócony do modułu menedżera-> pobierz wymagane zależności od modułu.
Rafał Dowgird,
Innymi słowy, zasadniczo IoC jest implementacją używania DI. Czy dostaję to poprawnie?
dance2die

Odpowiedzi:

53

Definicje

Odwrócenie kontroli jest paradygmatem projektowym, którego celem jest zmniejszenie świadomości konkretnych implementacji z kodu struktury aplikacji i zapewnienie większej kontroli nad komponentami aplikacji specyficznymi dla domeny. W tradycyjnym systemie zaprojektowanym z góry na dół logiczny przepływ aplikacji i świadomość zależności płyną z najwyższych komponentów, od tych zaprojektowanych jako pierwsze, do tych zaprojektowanych jako ostatnie. W związku z tym odwrócenie kontroli jest prawie dosłowne odwrócenie świadomości kontroli i zależności w aplikacji.

Wstrzykiwanie zależności jest wzorcem używanym do tworzenia instancji klas, na których opierają się inne klasy, nie wiedząc w czasie kompilacji, która implementacja zostanie wykorzystana do zapewnienia tej funkcjonalności.

Pracować razem

Odwrócenie kontroli może wykorzystywać wstrzykiwanie zależności, ponieważ do stworzenia komponentów zapewniających określoną funkcjonalność potrzebny jest mechanizm. Istnieją i są używane inne opcje, np. Aktywatory, metody fabryczne itp., Ale frameworki nie muszą odwoływać się do tych klas narzędzi użytkowych, gdy klasy frameworku mogą zaakceptować zależność (potrzebne).

Przykłady

Jednym z przykładów tych koncepcji w praktyce jest środowisko wtyczek w Reflector . Wtyczki mają dużą kontrolę nad systemem, mimo że aplikacja nie wiedziała nic o wtyczkach w czasie kompilacji. Dla każdej z tych wtyczek wywoływana jest jedna metoda Inicjuj, jeśli pamięć służy, co przekazuje kontrolę nad wtyczką. Framework nie wie, co zrobią, po prostu pozwala im to zrobić. Kontrola została przejęta z głównej aplikacji i przekazana komponentowi wykonującemu określoną pracę; odwrócenie sterowania.

Struktura aplikacji umożliwia dostęp do jej funkcji za pośrednictwem różnych dostawców usług. Wtyczka otrzymuje odniesienia do dostawców usług podczas jej tworzenia. Zależności te pozwalają wtyczce dodawać własne pozycje menu, zmieniać sposób wyświetlania plików, wyświetlać własne informacje w odpowiednich panelach itp. Ponieważ zależności są przekazywane przez interfejs, implementacje mogą się zmieniać, a zmiany nie spowodują uszkodzenia kod, o ile umowa pozostaje nienaruszona.

W tym czasie do tworzenia wtyczek użyto metody fabrycznej z wykorzystaniem informacji konfiguracyjnych, odbicia i obiektu Activator (przynajmniej w .NET). Obecnie istnieją narzędzia, takie jak MEF , które pozwalają na szerszy zakres opcji podczas wstrzykiwania zależności, w tym zdolność środowiska aplikacji do akceptowania listy wtyczek jako zależności.

Podsumowanie

Chociaż te koncepcje mogą być używane i zapewniają korzyści niezależnie, razem pozwalają na napisanie znacznie bardziej elastycznego, wielokrotnego użytku i testowalnego kodu. Jako takie są ważnymi koncepcjami przy projektowaniu rozwiązań obiektowych.

Głaskanie pod brodę
źródło
3
Nie, IoC jest starszą koncepcją i jest niezależna od DI (która nie zależy od IoC). Na przykład weźmy szkielet Struts (Java): w dużym stopniu opiera się on na IoC, ale nie korzysta z DI.
Rogério
1
@ Rogério - Masz rację, że te dwie koncepcje nie wymagają siebie nawzajem. Zaktualizowałem moją odpowiedź, aby to wyjaśnić, a następnie szybko opisałem, w jaki sposób niektóre frameworki używają ich razem, aby umożliwić luźniejszy kod.
Chuck
Najprostszą aplikacją IoC byłaby prawdopodobnie ActionListener. Zamiast proceduralnej obsługi kodu, kod obsługi zdarzeń jest delegowany do kodu niestandardowego. Odwraca kontrolę.
Mike
0

Dobry artykuł do zrozumienia MKOl i DI http://martinfowler.com/articles/injection.html

IOC (Inversion of Control)

MKOl oznacza

  1. kodowanie do interfejsu (jeden komponent powinien zależeć od interfejsu innego komponentu, a nie od impl), i np

    interface iComp_2 {...}
    
    class Comp_1 {
        iComp_2 c2 = ….;
    }
    
  2. usunięcie kodu specyficznego dla implementacji komponentu, np

    Comp_1 {
        iComp_2 c2 = getComp_2_Impl(); // not new Comp_2_Impl();
    }
    

MKOl można osiągnąć w jeden z następujących sposobów:

1. DI (wstrzykiwanie zależności)

3 types of DI

1.1 Constructor Injection

1.2 Setter Injection

1.3 Interface Injection

2. Lokalizator usług

Pojemnik DI (Dependency Injection)

Określenie impl środowiska wykonawczego i czas braku kompilacji: określa w czasie wykonywania, która konkretna implementacja interfejsu ma być używana na podstawie jakiegoś pliku konfiguracyjnego (więc w czasie kompilacji nie wiemy, który impl będzie używany, a tym samym zwiększa konfigurowalność aplikacji) . Jest to implementacja, w której o konkretnej relacji między różnymi modułami decyduje się w „czasie wykonywania”.

Instancja impl po wstrzyknięciu zależności: po określeniu impl tworzy instancję, najpierw tworząc wszystkie jej zależności (określone w pliku konfiguracyjnym), a następnie wstrzykuje te zależności do impl

Instancja Zarządzanie cyklem życia: kontenery DI zwykle przechowują jedynie odniesienia do obiektów, których potrzebuje do zarządzania cyklami życia, lub które są ponownie wykorzystywane do przyszłych zastrzyków, takich jak singletony lub wagi latające. Po skonfigurowaniu do tworzenia nowych wystąpień niektórych składników dla każdego wywołania kontenera kontener zwykle zapomina o utworzonym obiekcie. W przeciwnym razie śmieciarz miałby trudności z zebraniem wszystkich tych obiektów, gdy nie były już używane.

Yatendra Goel
źródło
6
Czy naprawdę przeczytałeś artykuł o iniekcji? MKOl nie znaczy wcale, co mówi ta odpowiedź.
Rogério
-3

Powiedziałbym, że „Inwersja kontroli” jest sposobem zaprojektowania systemu, w którym wszystkie moduły są traktowane jako abstrakcyjne byty.

I „Dependency Injection” to implementacja, w której o konkretnej relacji między różnymi modułami decyduje się w „czasie wykonywania”.

mB.
źródło
-4

Odwrócenie kontroli jest ogólną koncepcją, w językach funkcjonalnych zwykle odbywa się za pomocą kontynuacji. To pozwala ci napisać API, w którym obie strony są „dzwoniącymi”, a żadna „osoba wywoływana”. W innych, bardziej statycznych środowiskach nie masz tej zdolności, więc potrzebujesz tego hacka, aby wstawić podpowiedzi do przepływu sterowania.

Javier
źródło