Odwrócenie kontroli i wstrzyknięcie zależności

525

Według artykułu napisanego przez Martina Fowlera , odwrócenie kontroli jest zasadą, w której przepływ sterowania programem jest odwrócony: zamiast programisty kontrolującego przepływ programu, źródła zewnętrzne (szkielet, usługi, inne komponenty) przejmują kontrolę to. To tak, jakbyśmy podłączali coś do czegoś innego. Wspomniał przykład o EJB 2.0:

Na przykład interfejs Session Bean definiuje ejbRemove, ejbPassivate (przechowywany w pamięci dodatkowej) i ejbActivate (przywracany ze stanu pasywnego). Nie można kontrolować, kiedy te metody są wywoływane, tylko to, co robią. Kontener dzwoni do nas, nie nazywamy tego.

Prowadzi to do różnicy między frameworkiem a biblioteką:

Odwrócenie kontroli jest kluczową częścią tego, co odróżnia framework od biblioteki. Biblioteka jest zasadniczo zbiorem funkcji, które można wywoływać, w dzisiejszych czasach zwykle są one zorganizowane w klasy. Każde połączenie wykonuje pewną pracę i zwraca kontrolę klientowi.

Myślę, że punkt widzenia, że ​​DI to MKOl, oznacza, że ​​zależność obiektu jest odwrócona: zamiast kontrolować własne zależności, cykl życia ... coś innego robi dla ciebie. Ale, jak powiedziałeś mi o DI ręcznie, DI niekoniecznie musi być MKOl. Nadal możemy mieć DI i brak MKOl.

Jednak w tym artykule (z pococapsule, innej struktury IOC dla C / C ++) sugeruje, że z powodu IOC i DI, kontenery IOC i struktury DI są znacznie lepsze od J2EE, ponieważ J2EE miesza kod struktury z komponentami , nie czyniąc go więc Plain Old Java / C ++ Object (POJO / POCO).

Inwersja kontenerów kontrolnych innych niż wzorzec wstrzykiwania zależności (link do archiwum)

Dodatkowa lektura, aby zrozumieć, na czym polega problem ze starą platformą programistyczną opartą na komponentach, co prowadzi do drugiego artykułu powyżej: Dlaczego i co z inwersją kontroli (link do archiwum)

Moje pytanie : Czym dokładnie jest MKOl i DI? Jestem zdezorientowany. Oparty na pococapsule, IOC jest czymś ważniejszym niż odwrócenie kontroli między obiektami, programistami i frameworkami.

Amumu
źródło
2
Oto dobry komentarz na ten temat, IoC vs DI (Dependency Inject) vs SL (Service Locator): tinyurl.com/kk4be58 - Wyciąg z adresu URL: IoC vs DI (Dependency Injection)? IoC to ogólna koncepcja, w której sterowanie przepływem jest odwracane z kodu klienta do frameworka, który „robi coś dla klienta”. SL (Service Locator) i DI (Dependency Injection) to dwa wzorce projektowe wywodzące się z IoC.
Swab.Jat
Aby dodać moje dwa centy, jeśli ktoś jest zainteresowany tym, jak zastrzyk zależności może być pomocny w motywie kawiarni, napisałem artykuł na ten temat tutaj: digigene.com/design-patterns/dependency-injection-coffeeshop
Ali Nem
3
przyzwoity artykuł dla początkujących asimplify.com/dependency-injection-inversion-control
Khawaja Asim
Odwrócenie zależności: zależą od abstrakcji, a nie od konkrecji. Odwrócenie kontroli: Main vs Abstraction i jak Main jest klejem systemów. Oto kilka dobrych postów na ten temat: coderstower.com/2019/03/26/… coderstower.com/2019/04/02/… coderstower.com/2019/04/09/…
Daniel Andres Pelaez Lopez
przeczytaj o tym głęboko, to wyczyści wszystkie martinfowler.com/articles/…
Dushman

Odpowiedzi:

644

IoC to ogólny termin, który oznacza, że ​​aplikacja nie wywołuje metod w ramach, a platforma wywołuje implementacje dostarczone przez aplikację.

DI jest formą IoC, w której implementacje są przekazywane do obiektu przez wyszukiwanie konstruktorów / ustawiaczy / usług, od których obiekt będzie „zależał”, aby zachowywać się poprawnie.

IoC bez korzystania z DI , na przykład, byłby wzorzec szablonu, ponieważ implementację można zmienić tylko poprzez podklasę.

Ramy DI są zaprojektowane do korzystania z DI i mogą definiować interfejsy (lub Adnotacje w Javie), aby ułatwić przekazywanie w implementacjach.

Kontenery IoC to frameworki DI, które mogą działać poza językiem programowania. W niektórych można skonfigurować, które implementacje mają być używane w plikach metadanych (np. XML), które są mniej inwazyjne. Z niektórymi możesz zrobić IoC, co normalnie byłoby niemożliwe, jak wstrzyknięcie implementacji na punktach cięcia .

Zobacz także ten artykuł Martina Fowlera .

Garrett Hall
źródło
2
Dziękuję za odpowiedź. Ale drugi artykuł sugeruje, że w przypadku MKOl pojemniki MKOI są znacznie lepsze od EJB, podczas gdy Martin Fowler sugeruje, że EJB jest typowym przykładem MKOl.
Amumu
5
Zarządzanie EJB jest naprawdę typowym przykładem IoC. Widać to po fakcie, że cyklem życia EJB zarządza kontener, a nie programista. Programista nie tworzy ani nie niszczy instancji EJB, ponieważ kontrola jest delegowana na serwer . Taka jest koncepcja IoC: zewnętrzny kod kontroluje, kiedy twój kod jest wywoływany, co zwykle jest odwrotnością tego, co robiono przez większość czasu.
brandizzi
2
IoC to ogólny termin, który oznacza, że ​​aplikacja nie wywołuje metod w ramach, a platforma wywołuje implementacje dostarczone przez aplikację. Czy możesz wyjaśnić więcej na ten temat?
Imad Alazani
21
Aka zasady Hollywood , „nie do nas zadzwonić, będziemy cię nazywają”. Pozostawia wywołanie w strukturze, a nie w aplikacji.
Garrett Hall
@ImadAlazani, lepiej przeczytaj artykuł dołączony przez Garretta, który jest szczegółową dyskusją na temat odwracania kontroli z kodu aplikacji do frameworka.
MengT,
210

Krótko mówiąc, IoC jest znacznie szerszym pojęciem, które obejmuje między innymi DI

Termin Inversion of Control (IoC) pierwotnie oznaczał dowolny styl programowania, w którym ogólna struktura lub środowisko wykonawcze kontrolowało przebieg programu

Zanim DI miał swoją nazwę, ludzie zaczęli odnosić się do frameworków zarządzających zależnościami jako Inversion of Control Containers, a wkrótce znaczenie IoC stopniowo zmieniło się w to szczególne znaczenie: Inversion of Control over Dependencies.

Inwersja kontroli (IoC) oznacza, że ​​obiekty nie tworzą innych obiektów, na których polegają w swojej pracy. Zamiast tego pobierają potrzebne im obiekty ze źródła zewnętrznego (na przykład plik konfiguracyjny xml).

Wstrzykiwanie zależności (DI) oznacza, że ​​odbywa się to bez interwencji obiektu, zwykle przez komponent szkieletowy, który przekazuje parametry konstruktora i ustawia właściwości.

Tomasz Jaskuλa
źródło
1
Wygląda na to, że IoC to kolejny termin na zasadę Inwersji Depresji, prawda?
Todd Vance
@ToddVance - Tak, myślę, że IoC i DIP to to samo. DIP i DI to nie to samo. IoC można wykonać bez DI, ale DI nie można wykonać bez IoC.
Eljay,
2
@ToddVance - Nie, DIP i IoC nie są synonimami i nie są powiązane.
TSmith
3
Ha, dlatego jestem tutaj w tym temacie ... „Odwrócenie kontroli nad iniekcją zależności”
Todd Vance
50

wprowadź opis zdjęcia tutaj
źródło

IoC ( I nWersja O F C kontroli twoj ego): - Jest to ogólny termin i realizowane na kilka sposobów (imprezy delegaci etc).

DI ( wstrzyknięcie D ependencji I ): - DI jest podtypem IoC i jest implementowany przez wstrzyknięcie konstruktora, wstrzyknięcie setera lub wstrzyknięcie interfejsu .

Ale Spring obsługuje tylko następujące dwa typy:

  • Zastrzyk setera
    • DI oparty na setterach jest realizowany przez wywoływanie metod setter na komponentach bean użytkownika po wywołaniu konstruktora bez argumentów lub statycznej metody fabryki bez argumentów w celu utworzenia ich komponentu bean.
  • Wtrysk Konstruktora
    • DI oparty na konstruktorze jest realizowany przez wywoływanie konstruktora z wieloma argumentami, z których każdy reprezentuje współpracownika. Za jego pomocą możemy sprawdzić, czy wstrzyknięte komponenty bean nie są zerowe i nie działają szybko (niepowodzenie w czasie kompilacji, a nie w czasie wykonywania), więc podczas uruchamiania samej aplikacji otrzymujemy NullPointerException: bean does not exist. Wstrzykiwanie przez konstruktora jest najlepszą praktyką do wstrzykiwania zależności.
Premraj
źródło
1
nie jest poprawne stwierdzenie, że Wiosna nie obsługuje zastrzyku nieruchomości. To robi. Zgadzam się, że to zła praktyka.
kekko12
Spring @Autowired adnotation to moim zdaniem sposób na zastrzyk nieruchomości
Sajith
49

DI jest podzbiorem IoC

  • IoC oznacza, że ​​obiekty nie tworzą innych obiektów, na których polegają w swojej pracy. Zamiast tego pobierają potrzebne im obiekty z usługi zewnętrznej (na przykład pliku xml lub usługi pojedynczej aplikacji). 2 implementacje IoC, których używam, to DI i ServiceLocator.
  • DI oznacza, że ​​zasada IoC polegająca na uzyskiwaniu zależnych obiektów odbywa się bez użycia konkretnych obiektów, ale abstrakcji (interfejsów). To sprawia, że ​​wszystkie komponenty mogą być testowane w łańcuchu, ponieważ komponent wyższego poziomu nie zależy od komponentu niższego poziomu, tylko od interfejsu. Próbne implementują te interfejsy.

Oto kilka innych technik osiągnięcia IoC .

Lapenkov Vladimir
źródło
Nie powiedziałbym, że IoC oznacza brak tworzenia obiektów. Gdy nie wywołujesz bezpośrednio metody klasowej, ale metodę interfejsu - jest to odwrócenie kontroli (jak w tym przypadku program wywołujący nie zależy od wywołania kodu) i nie jest w ogóle związany z tworzeniem obiektów. Jeszcze jednym przykładem IoC są wydarzenia i delegaci
Eugene Gorbovoy
19

Ponieważ wszystkie odpowiedzi podkreślają teorię, chciałbym zademonstrować na przykładzie pierwszego podejścia:

Załóżmy, że tworzymy aplikację, która zawiera funkcję wysyłania wiadomości SMS z potwierdzeniem po wysłaniu zamówienia. Będziemy mieć dwie klasy, jedną odpowiedzialną za wysyłanie SMS-ów (SMSService), a drugą odpowiedzialną za przechwytywanie danych wejściowych użytkownika (UIHandler), nasz kod będzie wyglądał jak poniżej:

public class SMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
    }
}

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        SMSService _SMSService = new SMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Powyższa implementacja nie jest zła, ale jest kilka problemów:
-) Załóżmy, że w środowisku programistycznym chcesz zapisywać SMS-y wysyłane do pliku tekstowego zamiast bramy SMS, aby to osiągnąć; w końcu zmienimy konkretną implementację (SMSService) na inną implementację, tracimy elastyczność i zmuszeni jesteśmy przepisać kod w tym przypadku.
-) Skończy się mieszanie obowiązków klas, nasz (UIHandler) nigdy nie powinien wiedzieć o konkretnej implementacji (SMSService), należy to zrobić poza klasami za pomocą „Interfejsów”. Gdy zostanie to zaimplementowane, da nam możliwość zmiany zachowania systemu poprzez zamianę (SMSService) używanej z inną próbną usługą, która implementuje ten sam interfejs, usługa ta zapisuje SMS-y do pliku tekstowego zamiast wysyłania do mobileNumber.

Aby rozwiązać powyższe problemy, używamy interfejsów, które zostaną zaimplementowane przez nasz (SMSService) i nowy (MockSMSService), w zasadzie nowy interfejs (ISMSService) ujawni takie same zachowania obu usług, jak poniższy kod:

public interface ISMSService
{
    void SendSMS(string phoneNumber, string body);
}

Następnie zmienimy naszą implementację (SMSService) na implementację interfejsu (ISMSService):

public class SMSService : ISMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
        Console.WriteLine("Sending SMS using gateway to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

Teraz będziemy mogli stworzyć nową usługę makiety (MockSMSService) z zupełnie inną implementacją przy użyciu tego samego interfejsu:

public class MockSMSService :ISMSService
{
    public void SendSMS(string phoneNumber, string body)
    {
        SaveSMSToFile(phoneNumber,body);
    }

    private void SaveSMSToFile(string mobileNumber, string body)
    {
        /*implementation for saving SMS to a file*/
        Console.WriteLine("Mocking SMS using file to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

W tym momencie możemy zmienić kod w (UIHandler), aby łatwo użyć konkretnej implementacji usługi (MockSMSService), jak poniżej:

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        ISMSService _SMSService = new MockSMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Osiągnęliśmy dużą elastyczność i wprowadziliśmy separację problemów w naszym kodzie, ale nadal musimy dokonać zmiany w podstawie kodu, aby przełączać się między dwiema usługami SMS. Musimy więc wdrożyć Dependency Injection .

Aby to osiągnąć, musimy zaimplementować zmianę w naszym konstruktorze klasy (UIHandler), aby przekazać przez nią zależność. W ten sposób kod korzystający z (UIHandler) może określić, która konkretna implementacja (ISMSService) użyć:

public class UIHandler
{
    private readonly ISMSService _SMSService;

    public UIHandler(ISMSService SMSService)
    {
        _SMSService = SMSService;
    }

    public void SendConfirmationMsg(string mobileNumber)
    {
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Teraz formularz interfejsu użytkownika, który będzie rozmawiał z klasą (UIHandler), jest odpowiedzialny za przekazanie implementacji interfejsu (ISMSService) do wykorzystania. Oznacza to, że odwróciliśmy kontrolę, (UIHandler) nie jest już odpowiedzialny za decyzję, której implementacji użyć, robi to kod wywołujący. Wdrożyliśmy zasadę Inwersji Kontroli, której DI jest jednym z jej rodzajów.

Kod formularza interfejsu użytkownika będzie następujący:

class Program
{
    static void Main(string[] args)
    {
        ISMSService _SMSService = new MockSMSService(); // dependency

        UIHandler _UIHandler = new UIHandler(_SMSService);
        _UIHandler.SendConfirmationMsg("96279544480");

        Console.ReadLine();
    }
}
JerryGoyal
źródło
Świetne wyjaśnienie
ZiviMagic,
19

IOC (Inversion Of Control) : Przekazanie kontroli kontenerowi w celu uzyskania instancji obiektu nazywa się Inversion of Control, co oznacza, że ​​zamiast tworzyć obiekt za pomocą nowego operatora, pozwól kontenerowi zrobić to za Ciebie.

DI (Dependency Injection) : Sposób wstrzykiwania właściwości do obiektu nazywa się Dependency Injection .

Mamy trzy rodzaje wstrzykiwania zależności :

  1. Wtrysk Konstruktora
  2. Zastrzyk setera / gettera
  3. Interfejs wtrysku

Sprężyna obsługuje tylko wtrysk konstruktora i wtrysk Settera / Gettera .

kn3l
źródło
5

Ale wiosenna dokumentacja mówi, że są takie same.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction

W pierwszym wierszu „ IoC jest również znany jako wstrzykiwanie zależności (DI) ”.

użytkownik3386493
źródło
1
Wydaje mi się, że próbowali się odnieść do tego, że DI to bardzo szeroko stosowany wzorzec projektowania IoC, który można niemal łatwo nazwać IoC aka DI - chyba że dokumentacja zawiera wyraźne odniesienia, które sugerują inaczej.
ha9u63ar
5
„IoC jest również znany jako wstrzykiwanie zależności (DI)” ... pióra koni!
MikeM
5

IoC - Odwrócenie kontroli jest terminem ogólnym, niezależnym od języka, w rzeczywistości nie tworzy obiektów, lecz opisuje, w jaki sposób powstaje obiekt mody.

DI - Dependency Injection to konkretny termin, w którym zapewniamy zależności obiektu w czasie wykonywania przy użyciu różnych technik wstrzykiwania, a mianowicie. Zastrzyk setera, wtrysk konstruktora lub wstrzyknięcie interfejsu.

Rahul Gupta
źródło
4

Odwrócenie kontroli to paradygmat projektowania, którego celem jest zapewnienie większej kontroli nad docelowymi komponentami aplikacji, które wykonują pracę.
Wstrzykiwanie zależności jest wzorcem używanym do tworzenia instancji obiektów, na których polegają inne obiekty bez wiedzy w czasie kompilacji, która klasa zostanie użyta do zapewnienia tej funkcjonalności.

Istnieje kilka podstawowych technik wdrażania odwrócenia kontroli. To są:

  • Korzystanie ze wzoru fabrycznego
  • Korzystanie z wzorca lokalizatora usług
  • Za pomocą wstrzyknięcia zależności dowolnego z poniższych typów:

    1). Zastrzyk konstruktora
    2). Zastrzyk setera
    3). Wstrzyknięcie interfejsu
Saurabh
źródło
4

DI i IOC to dwa wzorce projektowe, które koncentrują się głównie na zapewnieniu luźnego sprzężenia między komponentami , lub po prostu sposobem, w którym rozłączamy konwencjonalne zależności zależności między obiektami, aby obiekty nie były do ​​siebie szczelne.

W poniższych przykładach próbuję wyjaśnić oba te pojęcia.

Wcześniej piszemy taki kod

Public MyClass{
 DependentClass dependentObject
 /*
  At somewhere in our code we need to instantiate 
  the object with new operator  inorder to use it or perform some method.
  */ 
  dependentObject= new DependentClass();
  dependentObject.someMethod();
}

W przypadku wstrzykiwania zależności wtryskiwacz zależności zajmie się tworzeniem obiektów

Public MyClass{
 /* Dependency injector will instantiate object*/
 DependentClass dependentObject

 /*
  At somewhere in our code we perform some method. 
  The process of  instantiation will be handled by the dependency injector
 */ 

  dependentObject.someMethod();
}

Powyższy proces przekazania kontroli innemu (np. Kontenerowi) instancji i iniekcji można nazwać inwersją kontroli, a proces, w którym pojemnik IOC wstrzykuje dla nas zależność, można nazwać iniekcją zależności.

IOC jest zasadą, w której przepływ sterujący programu jest odwrócony: zamiast programisty sterującego przepływem programu , program steruje przepływem poprzez zmniejszenie narzutu na programistę . A proces wykorzystywany przez program do wstrzykiwania zależności jest określany jako DI

Obie koncepcje współpracują ze sobą, zapewniając nam sposób na napisanie znacznie bardziej elastycznego, wielokrotnego użytku i enkapsulowanego kodu, co czyni je ważnymi koncepcjami w projektowaniu rozwiązań obiektowych.

Polecam również przeczytać.

Co to jest wstrzyknięcie zależności?

Możesz również sprawdzić jedną z moich podobnych odpowiedzi tutaj

Różnica między inwersją kontroli i iniekcji zależności

samuelj90
źródło
3

Inwersja kontroli to ogólna zasada projektowania architektury oprogramowania, która pomaga w tworzeniu łatwych w utrzymaniu modułowych struktur oprogramowania wielokrotnego użytku.

Jest to zasada projektowa, w której przepływ kontroli jest „odbierany” z biblioteki zapisanej w formie ogólnej lub kodu wielokrotnego użytku.

Aby to lepiej zrozumieć, zobaczmy, jak kodowaliśmy w naszych wcześniejszych czasach kodowania. W językach proceduralnych / tradycyjnych logika biznesowa ogólnie kontroluje przepływ aplikacji i „wywołuje” ogólny kod lub funkcje wielokrotnego użytku. Na przykład w prostej aplikacji konsoli mój przepływ kontroli jest kontrolowany przez instrukcje mojego programu, które mogą obejmować wywołania niektórych ogólnych funkcji wielokrotnego użytku.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

Natomiast w przypadku IoC frameworki to kod wielokrotnego użytku, który „wywołuje” logikę biznesową.

Na przykład w systemie opartym na systemie Windows dostępna będzie już platforma do tworzenia elementów interfejsu użytkownika, takich jak przyciski, menu, okna i okna dialogowe. Kiedy piszę logikę biznesową mojej aplikacji, to zdarzenia frameworka będą wywoływały mój kod logiki biznesowej (po uruchomieniu zdarzenia), a NIE odwrotnie.

Chociaż kod frameworka nie zna mojej logiki biznesowej, nadal będzie wiedział, jak wywołać mój kod. Osiąga się to za pomocą zdarzeń / delegatów, wywołań zwrotnych itp. Tutaj kontrola przepływu jest „odwrócona”.

Zatem zamiast zależeć od przepływu kontroli na statycznie związanych obiektach, przepływ zależy od ogólnego wykresu obiektów i relacji między różnymi obiektami.

Dependency Injection to wzorzec projektowy, który implementuje zasadę IoC do rozwiązywania zależności obiektów.

Mówiąc prościej, kiedy próbujesz pisać kod, będziesz tworzyć i używać różnych klas. Jedna klasa (klasa A) może używać innych klas (klasa B i / lub D). Tak więc klasy B i D są zależnościami klasy A.

Prostą analogią będzie samochód klasy. Samochód może zależeć od innych klas, takich jak silnik, opony i inne.

Wstrzykiwanie zależności sugeruje, że zamiast klas zależnych (tutaj samochód klasy) tworzących zależności (silnik klasy i opona klasy), klasy należy wstrzyknąć konkretny przykład zależności.

Pozwala zrozumieć bardziej praktyczny przykład. Zastanów się, czy piszesz własnego TextEditora. Między innymi możesz mieć moduł sprawdzania pisowni, który zapewnia użytkownikowi możliwość sprawdzania literówek w jego tekście. Prostą implementacją takiego kodu może być:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

Na pierwszy rzut oka wszystko wygląda różowo. Użytkownik napisze tekst. Deweloper przechwyci tekst i wywoła funkcję CheckSpellings i znajdzie listę literówek, które pokaże użytkownikowi.

Wydaje się, że wszystko działa świetnie, aż pewnego pięknego dnia, gdy jeden użytkownik zacznie pisać po francusku w edytorze.

Aby zapewnić obsługę większej liczby języków, potrzebujemy więcej sprawdzania pisowni. Prawdopodobnie francuski, niemiecki, hiszpański itp.

Tutaj stworzyliśmy ściśle powiązany kod z „angielskim” SpellCheckerem ściśle powiązanym z naszą klasą TextEditor, co oznacza, że ​​nasza klasa TextEditor jest zależna od EnglishSpellChecker lub innymi słowy EnglishSpellCheker jest zależnością dla TextEditor. Musimy usunąć tę zależność. Co więcej, nasz edytor tekstu potrzebuje sposobu, aby zachować konkretne odniesienie do dowolnego modułu sprawdzania pisowni w oparciu o uznanie programisty w czasie wykonywania.

Tak więc, jak widzieliśmy we wprowadzeniu DI, sugeruje, że klasie należy wstrzyknąć swoje zależności. Zatem obowiązkiem kodu wywołującego jest wstrzyknięcie wszystkich zależności do wywoływanej klasy / kodu. Możemy więc zrestrukturyzować nasz kod jako

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

W naszym przykładzie klasa TextEditor powinna otrzymać konkretną instancję typu ISpellChecker.

Teraz zależność można wprowadzić do Konstruktora, własności publicznej lub metody.

Spróbujmy zmienić naszą klasę za pomocą Constructor DI. Zmieniona klasa TextEditor będzie wyglądać mniej więcej tak:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Aby kod wywołujący podczas tworzenia edytora tekstu mógł wstrzyknąć odpowiedni typ sprawdzania pisowni do instancji TextEditor.

Możesz przeczytać cały artykuł tutaj

Amrit
źródło
3

IOC (Inversion Of Control): Przekazanie kontroli kontenerowi w celu uzyskania instancji obiektu nazywa się Inversion of Control. Oznacza to, że zamiast tworzyć obiekt za pomocą nowego operatora , niech kontener zrobi to za Ciebie.

DI (wstrzykiwanie zależności): Przekazywanie wymaganych parametrów (właściwości) z XML do obiektu (w KLASIE POJO) nazywa się wstrzykiwaniem zależności.

Suresh Kumar Msk
źródło
2

IOC wskazuje, że klasy zewnętrzne zarządzające klasami aplikacji, a klasy zewnętrzne oznaczają, że kontener zarządza zależnością między klasami aplikacji. podstawową koncepcją MKOl jest to, że programista nie musi tworzyć twoich obiektów, ale opisuje, w jaki sposób powinny być one tworzone.

Główne zadania wykonywane przez kontener IoC to: tworzenie instancji klasy aplikacji. skonfigurować obiekt. aby zestawić zależności między obiektami.

DI to proces zapewniania zależności obiektu w czasie wykonywania przy użyciu wstrzykiwania setera lub wstrzykiwania konstruktora.

Kunal
źródło
2

IOC (Inversion of Control) to zasadniczo koncepcja wzorca projektowania polegająca na usuwaniu zależności i rozdzielaniu ich w celu uczynienia przepływu nieliniowym, i pozwala kontenerowi / lub innemu podmiotowi zarządzać udostępnianiem zależności. W rzeczywistości jest to zgodne z zasadą Hollywood: „Nie dzwoń do nas, my zadzwonimy”. Podsumowując różnice.

Odwrócenie kontroli: - Jest to ogólny termin na rozdzielenie zależności i delegowanie ich udostępniania, i można to zrealizować na kilka sposobów (zdarzenia, delegaci itp.).

Iniekcja zależności: - DI jest podtypem IOC i jest realizowana przez iniekcję konstruktora, iniekcję setera lub metodę iniekcji.

Poniższy artykuł opisuje to bardzo starannie.

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO

supernowa
źródło
1

Myślę, że pomysł można jasno przedstawić bez wchodzenia w chwasty zorientowane obiektowo, które wydają się mętne.

// dependency injection
function doSomething(dependency) {
    // do something with your dependency
}

// in contrast to creating your dependencies yourself
function doSomething() {
    dependency = getDependencySomehow()
}

// inversion of control
application = makeApp(authenticate, handleRequest, sendResponse)
application.run(getRequest())

// in contrast to direct control or a "library" style
application = makeApp()
request = application.getRequest()

if (application.authenticate(request.creds)) {
    response = application.handleRequest(request)
    application.sendResponse(response)
}

Jeśli przechylisz głowę i zmrużysz oczy, zobaczysz, że DI jest szczególną implementacją IoC z konkretnymi obawami. Zamiast wstrzykiwać modele i zachowania do środowiska aplikacji lub operacji wyższego rzędu, wstrzykujesz zmienne do funkcji lub obiektu.

Rich Remer
źródło
0

Zacznijmy od D z SOLID i spójrzmy na DI i IoC z książki Scotta Milletta „Professional ASP.NET Design Patterns”:

Zasada inwersji zależności (DIP)

DIP jest o izolowanie swoich klas z wdrożeń konkretnych i posiadające im zależeć na abstrakcyjnych klas lub interfejsów. Promuje mantrę kodowania do interfejsu, a nie implementacji, co zwiększa elastyczność w systemie, zapewniając, że nie jesteś ściśle powiązany z jedną implementacją.

Wstrzykiwanie zależności (DI) i inwersja kontroli (IoC)

Z DIP są ściśle powiązane zasady DI i IoC. DI jest czynnością polegającą na dostarczaniu niskiego poziomu lub klasy zależnej za pośrednictwem konstruktora, metody lub właściwości. W połączeniu z DI te klasy zależne można odwrócić na interfejsy lub klasy abstrakcyjne, które doprowadzą do luźno sprzężonych systemów, które są wysoce testowalne i łatwe do zmiany.

W IoC przepływ kontroli systemu jest odwrócony w porównaniu do programowania proceduralnego. Przykładem tego jest kontener IoC , którego celem jest wstrzykiwanie usług do kodu klienta bez kodu klienta określającego konkretną implementację. Sterowanie w tym przypadku, które jest odwrócone, jest działaniem klienta uzyskującego usługę.

Millett, C (2010). Profesjonalne wzorce projektowe ASP.NET. Wiley Publishing. 7-8.

GorkemHalulu
źródło
0

// ICO, DI, 10 lat temu, tak było:

public class  AuditDAOImpl implements Audit{

    //dependency
    AuditDAO auditDAO = null;
        //Control of the AuditDAO is with AuditDAOImpl because its creating the object
    public AuditDAOImpl () {
        this.auditDAO = new AuditDAO ();
    }
}

Teraz z wiosną 3,4 lub najnowszą jest jak poniżej

public class  AuditDAOImpl implements Audit{

    //dependency

     //Now control is shifted to Spring. Container find the object and provide it. 
    @Autowired
    AuditDAO auditDAO = null;

}

Ogólnie rzecz biorąc, kontrola jest odwrócona od starej koncepcji sprzężonego kodu do struktur takich jak Spring, która udostępnia obiekt. To jest IOC, o ile wiem, i wstrzykiwanie zależności, jak wiesz, gdy wstrzykujemy zależny obiekt do innego obiektu za pomocą Konstruktora lub ustawiaczy. Zastrzyk zasadniczo oznacza przekazanie go jako argumentu. Wiosną mamy konfigurację opartą na XML i adnotacjach, w której definiujemy obiekt komponentu bean i przekazujemy obiekt zależny za pomocą stylu iniekcji konstruktora lub setera.

Vaibs
źródło
0

Znalazłem najlepszy przykład na Dzone.com, który naprawdę pomaga zrozumieć prawdziwe różnice między IOC i DI

„IoC ma miejsce, gdy ktoś inny tworzy dla ciebie obiekty”. Dlatego zamiast pisać „nowe” słowo kluczowe (na przykład MyCode c = new MyCode ()) w kodzie, obiekt jest tworzony przez kogoś innego. Ten „ktoś inny” jest zwykle określany jako kontener IoC. Oznacza to, że przekazujemy kontenerowi rrsponsibility (control), aby uzyskać instancję obiektu, nazywa się Inversion of Control. Oznacza to, że zamiast tworzyć obiekt za pomocą nowego operatora, niech kontener zrobi to za Ciebie.

   DI(Dependency Injection):  Way of injecting properties to an object is 
   called 
  Dependency injection.
   We have three types of Dependency injection
    1)  Constructor Injection
    2)  Setter/Getter Injection
    3)  Interface Injection
   Spring will support only Constructor Injection and Setter/Getter Injection.

Przeczytaj cały artykuł MKOl i Przeczytaj cały artykuł DI

Sachindra N. Pandey
źródło
0

1) DI to Child-> obj zależy od parent-obj. Czasownik zależy jest ważny. 2) IOC to Child-> obj występujące pod platformą. gdzie platformą może być szkoła, college, klasa taneczna. Tutaj perform jest działaniem o różnych implikacjach pod dowolnym dostawcą platformy.

praktyczny przykład: `

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

`

-AB

Abhishek
źródło
0

Jeśli chodzi o to pytanie, powiedziałbym, że wiki zawiera już szczegółowe i łatwe do zrozumienia wyjaśnienia. Przytoczę tutaj najważniejsze.

Wdrożenie IoC

W programowaniu obiektowym istnieje kilka podstawowych technik implementacji inwersji sterowania. To są:

  1. Korzystanie z wzorca lokalizatora usług Korzystanie z wstrzykiwania zależności, na przykład Wstrzykiwanie konstruktora Wstrzykiwanie parametrów Wstrzykiwanie Settera Wstrzykiwanie interfejsu;
  2. Korzystanie z kontekstowego wyszukiwania;
  3. Korzystanie z wzorca projektowego metody szablonu;
  4. Używanie wzorca projektowania strategii

Co do wstrzykiwania zależności

wstrzykiwanie zależności jest techniką, w której jeden obiekt (lub metoda statyczna) dostarcza zależności drugiego obiektu. Zależność to obiekt, z którego można korzystać (usługa). Zastrzyk to przekazanie zależności do obiektu zależnego (klienta), który go użyje.

Hearen
źródło
0

Koncepcja IoC była początkowo słyszana w erze programowania proceduralnego. Dlatego z historycznego kontekstu IoC mówił o inwersji własności kontrolno przepływu tj. O tym, kto jest odpowiedzialny za wywoływanie funkcji w pożądanej kolejności - niezależnie od tego, czy są to same funkcje, czy też należy je odwrócić na jakąś jednostkę zewnętrzną.

Jednak po pojawieniu się OOP ludzie zaczęli rozmawiać o IoC w kontekście OOP, w którym aplikacje zajmują się także tworzeniem obiektów i ich relacjami, oprócz przepływu sterowania. Takie aplikacje chciały odwrócić własność tworzenia obiektów (a nie kontroli przepływu) i wymagały kontenera, który jest odpowiedzialny za tworzenie obiektów, cykl życia obiektu i wstrzykiwanie zależności obiektów aplikacji, eliminując w ten sposób obiekty aplikacji z tworzenia innego konkretnego obiektu.

W tym sensie DI nie jest tym samym co Io C , ponieważ nie dotyczy przepływu sterowania, ale jest rodzajem Io * , czyli odwróceniem własności tworzenia obiektów.

Co jest złego w moim sposobie wyjaśniania DI i IoC?

Fahim Farook
źródło