Większość przytoczonych przykładów użycia wstrzykiwania zależności możemy rozwiązać również przy użyciu wzorca fabrycznego. Wygląda na to, że jeśli chodzi o użycie / projektowanie, różnica między wtryskiem zależności a fabryką jest rozmyta lub cienka.
Kiedyś ktoś mi powiedział, że to, jak go używasz, robi różnicę!
Kiedyś użyłem StructureMap do kontenera DI, aby rozwiązać problem, później przeprojektowałem go do pracy z prostą fabryką i usunąłem odniesienia do StructureMap.
Czy ktoś może mi powiedzieć, jaka jest między nimi różnica i gdzie z czego korzystać, jaka jest najlepsza praktyka tutaj?
dependency-injection
factory-pattern
design-patterns
Binoj Antony
źródło
źródło
Odpowiedzi:
Podczas korzystania z fabryki Twój kod jest nadal odpowiedzialny za tworzenie obiektów. Poprzez DI przekazujesz tę odpowiedzialność innej klasie lub platformie, która jest niezależna od twojego kodu.
źródło
Manually-Injected Dependency
Sugerowałbym, aby koncepcje były jasne i proste. Dependency Injection jest bardziej architektonicznym wzorem do luźnego łączenia komponentów oprogramowania. Wzorzec fabryczny to tylko jeden ze sposobów rozdzielenia odpowiedzialności za tworzenie obiektów innych klas na inny byt. Wzorzec fabryczny można wywołać jako narzędzie do implementacji DI. Wstrzykiwanie zależności można wdrożyć na wiele sposobów, takich jak DI przy użyciu konstruktorów, mapowania plików xml itp.
źródło
Wstrzykiwanie zależności
Zamiast tworzyć same części, samochód pyta o części, które musi funkcjonować.
Fabryka
Składa elementy razem, aby stworzyć kompletny obiekt i ukrywa konkretny typ przed dzwoniącym.
Wynik
Jak widać, fabryki i DI wzajemnie się uzupełniają.
Czy pamiętasz złotowłosa i trzy niedźwiedzie? Cóż, zastrzyk zależności jest w pewnym sensie taki. Oto trzy sposoby na zrobienie tego samego.
Przykład # 1 - Jest to najgorsze, ponieważ całkowicie ukrywa zależność. Jeśli spojrzałeś na tę metodę jako na czarną skrzynkę, nie miałbyś pojęcia, że wymaga samochodu.
Przykład 2 - To jest trochę lepsze, ponieważ teraz wiemy, że potrzebujemy samochodu, ponieważ mijamy w fabryce samochodów. Ale tym razem mijamy za dużo, ponieważ cała metoda faktycznie potrzebuje samochodu. Mijamy fabrykę tylko po to, żeby zbudować samochód, kiedy samochód mógłby być zbudowany poza metodą i przekazany.
Przykład 3 - Jest to idealne rozwiązanie, ponieważ metoda pyta o dokładnie to , czego potrzebuje. Nie za dużo lub za mało. Nie muszę pisać MockCarFactory tylko po to, aby stworzyć MockCars, mogę przekazać próbkę bezpośrednio. Jest to bezpośrednie i interfejs nie kłamie.
Ten Google Talk Talk Misko Hevery jest niesamowity i jest podstawą tego, z czego zaczerpnąłem mój przykład. http://www.youtube.com/watch?v=XcT4yYu_TTs
źródło
Powód wstrzykiwania zależności (DI) i wzorców fabrycznych jest podobny, ponieważ są to dwie implementacje Inversion of Control (IoC), która jest architekturą oprogramowania. Mówiąc wprost, są to dwa rozwiązania tego samego problemu.
Aby odpowiedzieć na pytanie, główną różnicą między wzorcem fabrycznym a DI jest sposób uzyskiwania odniesienia do obiektu. Z iniekcją zależności, jak sama nazwa wskazuje, wstrzyknięto odwołanie lub podano kod. W przypadku wzorca fabrycznego kod musi żądać odwołania, aby kod pobierał obiekt. Obie implementacje usuwają lub rozłączają powiązanie między kodem a bazową klasą lub typem odwołania do obiektu używanego przez kod.
Warto zauważyć, że wzorce fabryczne (a nawet abstrakcyjne wzorce fabryczne, które są fabrykami, które zwracają nowe fabryki, które zwracają odwołania do obiektów), mogą być zapisywane w celu dynamicznego wyboru lub połączenia z typem lub klasą obiektu żądanego w czasie wykonywania. To czyni je bardzo podobnymi (nawet bardziej niż DI) do wzorca Service Locator, który jest kolejną implementacją IoC.
Wzorzec projektowania fabryki jest dość stary (pod względem oprogramowania) i istnieje już od jakiegoś czasu. Od niedawnej popularności wzoru architektonicznego IoC odradza się.
Myślę, że jeśli chodzi o wzorce projektowania IoC: wtryskiwacze wstrzykują, lokalizatory lokalizują, a fabryki zostały zrefaktoryzowane.
źródło
Istnieją problemy, które można łatwo rozwiązać za pomocą wstrzykiwania zależności, których nie da się tak łatwo rozwiązać za pomocą zestawu fabryk.
Niektóre różnice między z jednej strony inwersją kontroli i iniekcją zależności (IOC / DI), a z drugiej strony lokalizatorem usług lub pakietem fabryk (fabryka), to:
IOC / DI to kompletny ekosystem obiektów i usług domenowych sam w sobie. Ustawia wszystko dla ciebie w określony sposób. Obiekty i usługi domeny są konstruowane przez kontener i nie konstruują się same: dlatego nie mają żadnych zależności od kontenera ani żadnych fabryk. IOC / DI pozwala na bardzo wysoki stopień konfigurowalności, przy czym cała konfiguracja znajduje się w jednym miejscu (konstrukcja kontenera) w najwyższej warstwie aplikacji (GUI, interfejs WWW).
Factory streszcza niektóre elementy konstrukcji i usług domeny. Ale obiekty i usługi domenowe są nadal odpowiedzialne za wymyślenie, jak się konstruować i jak zdobyć wszystkie rzeczy, na których polegają. Wszystkie te „aktywne” zależności są filtrowane przez wszystkie warstwy aplikacji. Nie ma jednego miejsca do skonfigurowania wszystkiego.
źródło
Jedną wadą DI jest to, że nie może on inicjować obiektów logiką. Na przykład, kiedy muszę utworzyć postać o losowej nazwie i wieku, DI nie jest wyborem w stosunku do wzorca fabrycznego. Dzięki fabrykom możemy łatwo kapsułkować losowy algorytm z tworzenia obiektów, który obsługuje jeden z wzorców projektowych o nazwie „Hermetyzuj to, co się zmienia”.
źródło
Od: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
źródło
Uważam, że DI jest rodzajem warstwy abstrakcji w fabrykach, ale zapewniają one również korzyści wykraczające poza abstrakcję. Prawdziwa fabryka wie, jak utworzyć pojedynczy typ i skonfigurować go. Dobra warstwa DI zapewnia, poprzez konfigurację, tworzenie i konfigurowanie wielu typów.
Oczywiście w przypadku projektu z kilkoma prostymi typami, które wymagają stosunkowo stabilnej logiki biznesowej w ich konstrukcji, wzór fabryczny jest prosty do zrozumienia, wdrożenia i działa dobrze.
OTOH, jeśli masz projekt zawierający wiele typów, których implementacje oczekujesz często zmieniać, DI daje ci elastyczność dzięki swojej konfiguracji, aby wykonywać to w czasie wykonywania bez konieczności ponownej kompilacji fabryk.
źródło
Teoria
Należy wziąć pod uwagę dwa ważne punkty:
Kto tworzy przedmioty
Jakimi obiektami zarządza:
Praktyczny przykład wykorzystania zastrzyku zarówno fabrycznego, jak i zależnościowego w jednym projekcie
Moduł aplikacji do tworzenia zamówienia, który zawiera wiele wpisów o nazwie linia zamówienia.
Załóżmy, że chcemy stworzyć następującą architekturę warstw:
Obiektami domenowymi mogą być obiekty przechowywane w bazie danych. Repozytorium (DAO) pomaga w pobieraniu obiektów z bazy danych. Usługa zapewnia API dla innych modułów. Pozwala na operacje na
order
modulePodmioty, które będą w bazie danych to Order i OrderLine. Zamówienie może mieć wiele linii zamówień.
Teraz przychodzi ważna część projektu. Czy moduły poza tym powinny tworzyć i zarządzać OrderLines we własnym zakresie? Nie. Linia zamówienia powinna istnieć tylko wtedy, gdy masz z nią powiązane zamówienie. Byłoby najlepiej, gdybyś mógł ukryć wewnętrzne wdrożenie dla klas zewnętrznych.
Ale jak stworzyć Zamówienie bez wiedzy o OrderLines?
Fabryka
Ktoś, kto chce utworzyć nowe zamówienie, użył OrderFactory (co ukryje szczegóły dotyczące tego, jak tworzymy zamówienie).
Tak to będzie wyglądać w IDE. Klasy poza
domain
pakietem będą używaneOrderFactory
zamiast konstruktora wewnątrzOrder
OrderRepository i OrderService są zarządzane przez strukturę wstrzykiwania zależności. Repozytorium odpowiada za zarządzanie operacjami CRUD w bazie danych. Usługa wstrzykuje repozytorium i używa go do zapisywania / znajdowania poprawnych klas domen.
źródło
[Factory]: Usually responsible for creation of stateful objects [Dependency Injections] More likely to create stateless objects
Nie rozumiem dlaczegoWiem, że to pytanie jest stare, ale chciałbym dodać moje pięć centów,
Myślę, że wstrzykiwanie zależności (DI) jest pod wieloma względami konfigurowalnym wzorcem fabrycznym (FP) iw tym sensie wszystko, co można zrobić z DI, będzie w stanie zrobić z taką fabryką.
W rzeczywistości, jeśli na przykład używasz sprężyny, masz opcję automatycznego zasilania (DI) lub robienia czegoś takiego:
A następnie użyj tego wystąpienia „mb”, aby cokolwiek zrobić. Czy to nie jest wezwanie do fabryki, która zwróci ci instancję?
Jedyną prawdziwą różnicą, którą zauważam między większością przykładów FP, jest to, że możesz skonfigurować, co „myBean” znajduje się w xml lub w innej klasie, a framework będzie działał jak fabryka, ale poza tym jest to to samo, a ty może mieć z pewnością Fabrykę, która czyta plik konfiguracyjny lub pobiera implementację zgodnie z potrzebami.
A jeśli zapytasz mnie o moją opinię (i wiem, że nie), wierzę, że DI robi to samo, ale tylko zwiększa złożoność rozwoju, dlaczego?
Cóż, po pierwsze, aby wiedzieć, jaka implementacja jest używana dla dowolnego komponentu bean, którego używasz automatycznie w DI, musisz przejść do samej konfiguracji.
ale ... co z obietnicą, że nie będziesz musiał znać implementacji obiektu, którego używasz? pfft! poważnie? kiedy zastosujesz takie podejście ... czy nie jesteś tym samym, który pisze implementację? a nawet jeśli nie, to czy nie prawie cały czas patrzysz, jak implementacja robi to, co powinna?
i na koniec, nie ma znaczenia, ile framework DI obiecuje ci, że będziesz budował rzeczy od niego niezwiązane , bez zależności od ich klas, jeśli używasz frameworka, budujesz wszystko na nim, jeśli musisz zmień podejście lub ramy, to nie będzie łatwe zadanie ... KIEDYKOLWIEK! ... ale ponieważ budujesz wszystko wokół tego konkretnego środowiska, zamiast martwić się o najlepsze rozwiązanie dla Twojej firmy, staniesz przed poważnym problemem.
W rzeczywistości jedyną prawdziwą aplikacją biznesową dla podejścia FP lub DI, którą widzę, jest konieczność zmiany implementacji używanych w środowisku wykonawczym , ale przynajmniej znane mi ramy nie pozwalają na to, musisz odejść wszystko idealne w konfiguracji w czasie programowania i jeśli potrzebujesz, użyj innego podejścia.
Tak więc, jeśli mam klasę, która działa w różny sposób w dwóch zakresach w tej samej aplikacji (powiedzmy, dwie firmy holdingu), muszę skonfigurować strukturę, aby utworzyć dwie różne komponenty i dostosować mój kod, aby z nich korzystać. Czy to nie to samo, gdybym napisał coś takiego:
tak samo jak to:
I to:
W każdym razie będziesz musiał coś zmienić w swojej aplikacji, czy to w klasach, czy w plikach konfiguracyjnych, ale musisz to zrobić ponownie.
Czy nie byłoby miło zrobić coś takiego:
I w ten sposób ustawiasz kod fabryki, aby uzyskać właściwą implementację w czasie wykonywania w zależności od zalogowanego przedsiębiorstwa użytkownika? Teraz to byłoby pomocne. Możesz po prostu dodać nowy jar z nowymi klasami i ustawić reguły, może nawet w czasie wykonywania (lub dodać nowy plik konfiguracyjny, jeśli pozostawisz tę opcję otwartą), bez zmian w istniejących klasach. To byłaby fabryka dynamiczna!
czy nie byłoby to bardziej pomocne niż konieczność napisania dwóch konfiguracji dla każdego przedsiębiorstwa, a może nawet posiadania dwóch różnych aplikacji dla każdego?
Możesz mi powiedzieć, że nie muszę nigdy zmieniać przełącznika w czasie wykonywania, więc konfiguruję aplikację, a jeśli odziedziczę klasę lub użyję innej implementacji, po prostu zmieniam konfigurację i wdrożyłem ponownie. Ok, można to również zrobić w fabryce. I szczerze mówiąc, ile razy to robisz? może tylko wtedy, gdy masz aplikację, która będzie używana gdzie indziej w Twojej firmie, i przekażesz kod innemu zespołowi, a oni zrobią takie rzeczy. Ale hej, można to również zrobić w fabryce, a byłoby jeszcze lepiej w dynamicznej fabryce !!
W każdym razie sekcja komentarzy, jeśli jesteś otwarta, aby mnie zabić.
źródło
MKOl to koncepcja realizowana na dwa sposoby. Tworzenie zależności i wstrzykiwanie zależności, fabryka / fabryka abstrakcyjna są przykładem tworzenia zależności. Wstrzykiwanie zależności jest konstruktorem, ustawiaczem i interfejsem. Rdzeń MKOl nie polega na konkretnych klasach, ale definiuje abstrakt metod (powiedzmy klasę interfejsu / klasy abstrakcyjnej) i używa tego abstraktu do wywoływania metody konkretnej klasy. Podobnie jak wzorzec fabryczny zwraca klasę bazową lub interfejs. Podobnie wstrzykiwanie zależności wykorzystuje klasę bazową / interfejs do ustawiania wartości dla obiektów.
źródło
Dzięki wstrzykiwaniu zależności klient nie musi samodzielnie uzyskiwać swoich zależności, wszystko jest wcześniej przygotowane.
W przypadku fabryk ktoś musi do nich zadzwonić, aby przenieść wygenerowane obiekty do miejsca, w którym są potrzebne.
Różnica polega głównie na tej jednej linii, w której odbywa się wywoływanie fabryki i pobieranie skonstruowanego obiektu.
Ale w fabrykach musisz napisać 1 linię wszędzie tam, gdzie potrzebujesz takiego obiektu. Z DI musisz tylko raz stworzyć okablowanie (relację między użytkowaniem a stworzonym obiektem) i po prostu polegać na obecności obiektu później. Z drugiej strony DI często wymaga nieco więcej (ile zależy od frameworka) pracy po stronie przygotowawczej.
źródło
Miałem to samo pytanie, gdy tylko przeczytałem o DI i znalazłem się w tym poście. Więc w końcu to zrozumiałem, ale proszę, popraw mnie, jeśli się mylę.
„Dawno temu istniały małe królestwa z własnymi organami zarządzającymi kontrolującymi i podejmującymi decyzje na podstawie własnych pisemnych zasad. Później utworzono duży rząd eliminujący wszystkie te małe organy zarządzające, które mają jeden zestaw zasad (konstytucji) i są wdrażane przez sądy”
Organami zarządzającymi małych królestw są „fabryki”
Duży rząd to „Dependency Injector”.
źródło
Możesz rzucić okiem na ten link, aby porównać dwa (i inne) podejścia w prawdziwym przykładzie.
Zasadniczo, gdy zmieniają się wymagania, modyfikujesz więcej kodu, jeśli używasz fabryk zamiast DI.
Dotyczy to również ręcznego DI (tzn. Gdy nie ma zewnętrznego frameworka, który zapewnia zależności dla twoich obiektów, ale przekazujesz je w każdym konstruktorze).
źródło
Większość odpowiedzi tutaj wyjaśnia różnice koncepcyjne i szczegóły implementacji obu. Nie udało mi się jednak znaleźć wyjaśnienia na temat różnicy w aplikacji, która IMO jest najważniejsza i o którą zapytał PO. Pozwól mi więc ponownie otworzyć ten temat ...
Dokładnie. W 90% przypadków można uzyskać odniesienie do obiektu za pomocą Factory lub DI i zwykle kończy się to drugim. W kolejnych 10% przypadków użycie Fabryki jest tylko poprawnym sposobem . Przypadki te obejmują uzyskiwanie obiektów przez zmienną przy parametrach środowiska wykonawczego. Lubię to:
W takim przypadku uzyskanie
client
od DI nie jest możliwe (lub przynajmniej wymaga trochę brzydkiego obejścia). Zatem ogólną zasadą jest podejmowanie decyzji: jeśli można uzyskać zależność bez parametrów obliczonych w czasie wykonywania, wówczas preferowane jest DI, w przeciwnym razie należy użyć Fabrycznie.źródło
wierzę, że DI to sposób konfiguracji lub tworzenia instancji fasoli. DI można wykonać na wiele sposobów, takich jak konstruktor, setter-getter itp.
Wzór fabryczny to tylko kolejny sposób tworzenia instancji fasoli. ten wzorzec będzie używany głównie, gdy trzeba tworzyć obiekty przy użyciu fabrycznego wzorca projektowego, ponieważ podczas używania tego wzorca nie konfigurujesz właściwości fasoli, tylko tworzysz obiekt.
Sprawdź ten link: Wstrzykiwanie zależności
źródło
Binoj,
Nie sądzę, że musisz wybierać między sobą.
Przeniesienie zależnej klasy lub interfejsu do konstruktora lub ustawiacza klasy odbywa się według wzorca DI. Obiekt przekazywany do konstruktora lub zestawu można zaimplementować w programie Factory.
Kiedy użyć? Użyj wzoru lub wzorów, które znajdują się w sterówce programisty. W czym czują się najbardziej komfortowo i są najłatwiejsze do zrozumienia.
źródło
Uważam, że 3 ważne aspekty rządzą obiektami i ich wykorzystaniem:
1. Tworzenie instancji (klasy wraz z ewentualną inicjalizacją).
2. Zastrzyk (tak utworzonej instancji) tam, gdzie jest wymagany.
3. Zarządzanie cyklem życia (tak utworzonej instancji).
Przy użyciu wzorca fabrycznego osiąga się pierwszy aspekt (tworzenie instancji), ale pozostałe dwa są wątpliwe. Klasa korzystająca z innych instancji musi zakodować na stałe fabryki (zamiast tworzenia instancji), co utrudnia utratę zdolności łączenia. Ponadto zarządzanie cyklem życiainstancji staje się wyzwaniem w dużej aplikacji, w której fabryka jest używana w wielu miejscach (szczególnie jeśli fabryka nie zarządza cyklem życia instancji, którą zwraca, robi się brzydka).
Z drugiej strony, używając DI (wzorca IoC), wszystkie 3 są wyodrębniane poza kodem (do kontenera DI), a zarządzana fasola nie potrzebuje niczego o tej złożoności. Luźne połączenie , bardzo ważny cel architektoniczny można osiągnąć cicho i wygodnie. Kolejny ważny cel architektoniczny, rozdzielenie problemów można osiągnąć znacznie lepiej niż fabryki.
Podczas gdy fabryki mogą być odpowiednie do małych zastosowań, duże lepiej byłoby wybrać DI niż fabryki.
źródło
Moje myśli:
Dependecy Injection: przekazuj współpracowników jako parametry do konstruktorów. Dependency Injection Framework: ogólna i konfigurowalna fabryka do tworzenia obiektów, które będą przekazywane jako parametry do konstruktorów.
źródło
Struktura wtrysku jest implementacją Wzorca Fabrycznego.
Wszystko zależy od twoich wymagań. Jeśli musisz zaimplementować wzorzec fabryczny w aplikacji, jest bardzo prawdopodobne, że twoje wymagania zostaną spełnione przez jedną z niezliczonych implementacji frameworku.
Powinieneś wdrożyć własne rozwiązanie tylko wtedy, gdy twoje wymagania nie mogą być spełnione przez żaden z zewnętrznych frameworków. Im więcej kodu piszesz, tym więcej kodu musisz zachować. Kod jest zobowiązaniem, a nie aktywem.
Argumenty, które implementacje powinieneś zastosować, nie są tak fundamentalnie ważne, jak zrozumienie architektonicznych potrzeb Twojej aplikacji.
źródło
Wzorzec projektowania fabryki
Wzór fabryczny charakteryzuje się
Możesz zaobserwować kilka rzeczy, gdy zadajesz sobie pytanie, jak poniżej
Są one obsługiwane przez wstrzyknięcie zależności.
Zastrzyk zależności
Możesz mieć różne sposoby wstrzykiwania zależności. Dla uproszczenia puszczamy interfejs wtrysku
W DI kontener tworzy potrzebne instancje i „wstrzykuje” je do obiektu.
W ten sposób eliminuje instancję statyczną.
Przykład:
źródło
Z wartości nominalnej wyglądają tak samo
Mówiąc najprościej, Factory Pattern, Creational Pattern pomaga stworzyć nam obiekt - „Zdefiniuj interfejs do tworzenia obiektu”. Jeśli mamy rodzaj puli obiektów o wartości kluczowej (np. Słownik), przekazując klucz do fabryki (mam na myśli prosty wzorzec fabryczny), można rozwiązać typ. Zadanie wykonane! Z drugiej strony wydaje się, że to samo robi Dependency Injection Framework (takie jak Structure Map, Ninject, Unity ... itd.).
Ale ... „Nie wymyślaj koła ponownie”
Z architektonicznego punktu widzenia jest to warstwa wiążąca i „Nie wymyślaj koła ponownie”.
W przypadku aplikacji klasy korporacyjnej koncepcja DI jest bardziej warstwą architektoniczną, która określa zależności. Aby jeszcze bardziej to uprościć, możesz myśleć o tym jako o osobnym projekcie biblioteki klasowej, który rozwiązuje zależności. Główna aplikacja zależy od tego projektu, w którym moduł rozpoznawania zależności odnosi się do innych konkretnych implementacji i rozwiązywania zależności.
Oprócz „GetType / Create” z fabryki, najczęściej potrzebujemy więcej funkcji (możliwość używania XML do definiowania zależności, kpiny i testowania jednostek itp.). Ponieważ odwoływałeś się do mapy struktury, spójrz na listę funkcji mapy struktury . Jest to wyraźnie coś więcej niż rozwiązywanie prostych mapowań obiektów. Nie wymyślaj koła na nowo!
Jeśli masz tylko młotek, wszystko wygląda jak gwóźdź
W zależności od wymagań i rodzaju tworzonej aplikacji musisz dokonać wyboru. Jeśli ma tylko kilka projektów (może to być jeden lub dwa ..) i wiąże się z niewielkimi zależnościami, możesz wybrać prostsze podejście. To jak korzystanie z dostępu do danych ADO .Net w porównaniu z używaniem Entity Framework do prostych 1 lub 2 wywołań bazy danych, gdzie wprowadzenie EF jest przesadą w tym scenariuszu.
Ale w przypadku większego projektu lub jeśli projekt staje się większy, zdecydowanie polecam mieć warstwę DI z ramą i zrobić miejsce na zmianę używanego frameworka DI (Użyj fasady w głównej aplikacji (aplikacja sieci Web, interfejs WWW, pulpit) ..itp.).
źródło
W fabryce możesz grupować powiązane interfejsy, więc jeśli przekazane parametry mogą być pogrupowane w fabryce, to jest to również dobre rozwiązanie dla
constructor overinjection
tego kodu *):Spójrz na konstruktor, musisz go tylko przekazać
IAddressModelFactory
, więc mniej parametrów *):Widzisz w
CustomerController
wielu parametrach, tak, możesz to zobaczyć, ponieważconstructor overinjection
tak działa DI. I nie ma w tym nic złegoCustomerController
.*) Kod pochodzi z nopCommerce.
źródło
Mówiąc najprościej, metoda wtrysku zależnego od fabrycznego implikuje odpowiednio mechanizm pchający i ciągnący.
Mechanizm ściągania : klasa pośrednio zależy od metody fabrycznej, która z kolei ma zależność od konkretnych klas.
Mechanizm pchający: Element główny może być skonfigurowany ze wszystkimi zależnymi elementami w jednym miejscu, co zapewnia wysoką konserwację i luźne połączenie.
W przypadku metody Factory odpowiedzialność nadal spoczywa na klasie (choć pośrednio) na tworzeniu nowego obiektu, gdzie podobnie jak w przypadku wstrzykiwania zależności odpowiedzialność ta jest zlecana na zewnątrz (kosztem przecieku abstrakcji)
źródło
Myślę, że są one ortogonalne i mogą być używane razem. Pozwól, że pokażę ci przykład, z którym ostatnio spotkałem się w pracy:
Używaliśmy frameworka Spring w Javie dla DI. Klasa singleton (
Parent
) musiała utworzyć nowe obiekty innej klasy (Child
), a te miały złożoną współpracę:W tym przykładzie
Parent
musi odbieraćDepX
instancje tylko w celu przekazania ich doChild
konstruktora. Problemy z tym:Parent
ma większą wiedzęChild
niż powinnaParent
ma więcej współpracowników niż powinienChild
wymaga zmianyParent
Wtedy zdałem sobie sprawę,
Factory
że idealnie pasuje tutaj:Child
klasy, jak widaćParent
Child
, który może być scentralizowany w konfiguracji DI.To jest
Parent
klasa uproszczona iChildFactory
klasa:źródło
Wstrzykiwania zależności używasz, gdy dokładnie wiesz, jakiego rodzaju obiektów potrzebujesz w tym momencie. Podczas gdy w przypadku wzorca fabrycznego, po prostu delegujesz proces tworzenia obiektów do fabryki, ponieważ nie jesteś pewien, jakiego dokładnie rodzaju obiektów potrzebujesz.
źródło
Używam obu do stworzenia strategii Inversion Of Control z większą czytelnością dla programistów, którzy muszą ją utrzymywać po mnie.
Używam fabryki do tworzenia różnych obiektów warstwy (biznes, dostęp do danych).
Inny programista to zobaczy i podczas tworzenia obiektu warstwy biznesowej zajrzy do BusinessFactory, a Intellisense daje programistowi wszystkie możliwe warstwy biznesowe do utworzenia. Nie musisz grać w grę, znajdź interfejs, który chcę utworzyć.
Ta struktura jest już Inwersją Kontroli. Nie jestem już odpowiedzialny za tworzenie konkretnego obiektu. Ale nadal musisz zapewnić Dependency Injection, aby móc łatwo zmieniać rzeczy. Tworzenie własnego niestandardowego wtrysku zależności jest niedorzeczne, więc używam Unity. W ramach CreateCarBusiness () proszę Unity, aby zdecydowała, która klasa należy do tej klasy i jaka jest jej żywotność.
Więc mój kod Struktura wstrzykiwania zależności fabrycznej to:
Teraz mam zalety obu. Mój kod jest również bardziej czytelny dla innych programistów, jeśli chodzi o zakresy moich obiektów, których używam, zamiast Constructor Dependency Injection, który mówi tylko, że każdy obiekt jest dostępny podczas tworzenia klasy.
Używam tego do zmiany dostępu do bazy danych na niestandardową zakodowaną warstwę dostępu do danych podczas tworzenia testów jednostkowych. Nie chcę, aby moje testy jednostkowe komunikowały się z bazami danych, serwerami WWW, serwerami poczty e-mail itp. Muszą przetestować moją warstwę biznesową, ponieważ na tym polega inteligencja.
źródło
Moim zdaniem użycie wstrzykiwania zależności jest znacznie lepsze, jeśli: 1. wdrażasz kod na małej partycji, ponieważ dobrze radzi sobie on w oddzielaniu jednego dużego kodu. 2. Testowalność jest jednym z przypadków, w których użycie DI jest w porządku, ponieważ można łatwo wyśmiewać nieprzężone obiekty. za pomocą interfejsów możesz łatwo wyśmiewać i testować każdy obiekt. 3. Możesz jednocześnie poprawiać każdą część programu bez konieczności kodowania drugiej części programu, ponieważ jest on luźno oddzielony.
źródło