Co to jest odwrócenie kontroli i kiedy powinienem jej używać?

Odpowiedzi:

62

IoC (patrz Inwersja kontroli na Wikipedii) ma zastosowanie w przypadkach, w których składnik nie może wykonać zadania całkowicie, ponieważ nie ma niezbędnych informacji ani funkcji.

Najprostszym przykładem wzorca IoC są funkcje zwrotne w C. Na przykład możesz zadeklarować funkcję:

void Iterator(void *list, Func* f)

Która iteruje po listzastosowaniu ffunkcji do każdego z jej elementów. IteratorFunkcja nie wie, w jaki sposób każdy element zostanie przetworzony, po prostu zapewnić funkcję jako argument, i przetwarza je.

Jak pokazuje poprzedni przykład, IoC pozwala rozdzielić program na osobne komponenty, które się nie znają. Jedną z najpopularniejszych wersji IoC jest Dependecy Injection .

W przypadku wstrzykiwania zależności każdy komponent musi zadeklarować listę zależności wymaganych do wykonania swojego zadania. W czasie wykonywania specjalny komponent (ogólnie) o nazwie kontener IoC wykonuje wiązanie między tymi komponentami. Próbuje podać wartości dla opublikowanych zależności komponentów.

Oto przykład w pseudokodzie:

class Foo 
{ 
   <Require Boo>Constructor(Boo boo){ boo.DoSomething } 
}

W tym przykładzie klasa Fooma konstruktor, który wymaga argumentu typu, Booaby wykonać jakąś akcję.

Możesz utworzyć instancję klasy Fooza pomocą kodu podobnego do tego:

MyContainer.Create(typeof Foo)

MyContainer- jest kontenerem IoC , który dba o uzyskanie instancji Booi przekazanie jej do Fookonstruktora.

Podsumowując, IoC pozwala rozdzielić program na osobne części. Jest to dobre, ponieważ:

  • Komponenty można łatwo przetestować niezależnie.
  • Złożoność programu można zmniejszyć.
  • Możesz przełączyć komponenty na inną implementację.

Jednak w niektórych przypadkach IoC może utrudniać zrozumienie kodu.

Jeśli chcesz zobaczyć dobry przykład użycia świata rzeczywistego z IoC , rzucić okiem na Mircosoft Composite UI Application bloku i CompositeWPF

Mam nadzieję, że moje wyjaśnienie ci pomoże.

Pozdrawiam,
jang


źródło
1
Pięć lat później, ale nadal… To był doskonały opis. Dzięki.
Nick Hodges
4
Nigdzie nie wspomina się o IoC o tym, że kod staje się trudniejszy do odczytania. Czytelność jest priorytetem numer jeden, jeśli chcesz pisać świetne oprogramowanie. To nawet przewyższa Testowalność. Możesz oddzielić kod znacznie przekraczający jego użyteczność.
Arne Evertsson,
Czyli kod, który używa rozwiązania opartego na interfejsie dla wszystkich jego zależności, jest również oparty na projekcie IoC?
nikel
18

Ponieważ ostatnio sam się w to zagłębiłem i zachowałem wszystkie zakładki, poniższe informacje okazały się nieocenione przy poznawaniu IOC / DI.

Martin Fowlers Artykuł oryginalny na temat MKOl / DI

Kilka pojęć, które należy znać jako pierwsze

Doskonały zbiór samouczków IOC / DI

Rezerwuj na IOC / DI From Manning Press

Źródło i wyjaśnienie, jak stworzyć własny MKOl - ponieważ czytanie kodu źródłowego jest zawsze najlepszym sposobem na zrozumienie pojęcia.

Kris Erickson
źródło
4

Hej JMS, w zasadzie IoC / DI pozwoli ci zdefiniować implementację, której używasz raz, i zachowaj statyczną kopię swojego kontenera, aby odwoływała się za każdym razem, gdy chcesz się do niego odwoływać.

Wikipedia prawdopodobnie ci pomoże, ale chciałem odnieść się do twojej drugiej części - tak, wstrzyknięcie zależności można wykonać dla klas (tj. Za każdym razem, gdy ten typ klasy musi zostać przekazany do metody, użyj tej klasy), ale lepiej jest używaj interfejsów, ponieważ w ten sposób możesz zmienić wersję dostawcy, repozytorium itp., której używasz, po prostu odwołując się do niego w konfiguracji.

IE, powiedzmy, że masz interfejs do odczytu strumienia, a także implementację XMLStreamReader i SQLStreamReader. Następnie możesz przekazać odniesienie do interfejsu do swoich metod, a następnie w kontenerze IoC powiedz, którego użyć.

Tak więc możesz mieć publiczną listę ReadPeople (czytnik IStreamReader), aw swojej konfiguracji kontenera IoC powiedz to za każdym razem, gdy spodziewasz się, że IStreamReader używa SQLStreamReader.

Następnie, jeśli zmienisz zdanie później, musisz go zmienić tylko w jednym miejscu (konfiguracja kontenera) i nie będzie miało znaczenia, ile metod poprosi o IStreamReader, zawsze uzyska domyślną wartość, o której kazałeś kontenerowi Podaj, podac, zaserwowac.


źródło
3

Załóżmy, że masz walidator do sprawdzania, czy firma jest ważna w twoim systemie. Twój „BusinessValidator” może mieć pole typu AddressValidator, które weryfikuje adresową część firmy. Jeśli chcesz przetestować BusinessValidator bez wykonywania kodu zewnętrznego (tj. Kodu addressValidator), to jeśli użyłeś w swoim środowisku jakiegoś IoC / DI, możesz łatwo „wstrzyknąć” fałszywy adres Validator w jego miejsce i nie musisz się martwić o testowanie kod poza zakresem testowanej klasy.

codeLes
źródło