Na poziomie klasy jest to łatwe.
„Dependency Injection” po prostu odpowiada na pytanie „jak znajdę moich współpracowników” za pomocą „oni są na ciebie naciskani - nie musisz iść i sam ich zdobyć”. (Jest podobny - ale nie taki sam jak - „Inwersja kontroli”, gdzie na pytanie „w jaki sposób mam zamówić operacje na podstawie moich danych wejściowych?” Ma podobną odpowiedź).
Tylko korzyść, że posiadanie współpracownicy popchnął na ciebie jest to, że umożliwia kodu klienckiego do korzystania z klasy do komponowania wykres obiektu, który odpowiada swoją obecną potrzebę ... nie ma arbitralnie z góry określony kształt i zmienność na wykresie przez prywatnie decydując konkretne typy i cykl życia współpracowników.
(Wszystkie te inne korzyści, testowalność, luźne sprzężenie itp. Wynikają w dużej mierze z zastosowania interfejsów, a nie tyle z zależności wstrzykiwania zależności, chociaż DI naturalnie promuje stosowanie interfejsów).
Warto zauważyć, że jeśli unikniesz tworzenia własnych współpracowników, twoja klasa musi zatem uzyskać współpracowników od konstruktora, właściwości lub argumentu metody (ta druga opcja jest często pomijana, nawiasem mówiąc ... robi to nie zawsze ma sens, aby „kolaboranci klasy” byli częścią swojego „stanu”).
I to dobrze.
Na poziomie aplikacji ...
Tyle o widoku rzeczy dla poszczególnych klas. Załóżmy, że masz wiele klas, które działają zgodnie z zasadą „nie twórz własnych współpracowników” i chcesz złożyć z nich aplikację. Najprostszą rzeczą do zrobienia jest użycie starego dobrego kodu (bardzo przydatnego narzędzia do wywoływania konstruktorów, właściwości i metod!) Do skomponowania pożądanego wykresu obiektowego i dołożenia do niego pewnych danych wejściowych. (Tak, niektóre z tych obiektów na wykresie same w sobie będą obiektami-fabrykami, które zostały przekazane jako współpracownicy innym długowiecznym obiektom na wykresie, gotowym do obsługi ... nie można wstępnie zbudować każdego obiektu! ).
... potrzeba „elastycznego” skonfigurowania wykresu obiektowego aplikacji ...
W zależności od innych (niezwiązanych z kodem) celów możesz chcieć dać użytkownikowi końcowemu kontrolę nad wdrożonym w ten sposób wykresem obiektowym. To prowadzi cię w kierunku schematu konfiguracji, niezależnie od tego, czy jest to plik tekstowy własnego projektu z pewnymi parami nazwa / wartość, plik XML, niestandardowy DSL, deklaratywny język opisu graficznego, taki jak YAML, imperatywny język skryptowy, taki jak JavaScript, lub coś innego odpowiedniego do wykonywanego zadania. Wszystko, czego potrzeba, aby skomponować prawidłowy wykres obiektowy, w sposób odpowiadający potrzebom użytkowników.
... może być znaczącą siłą projektową.
W najbardziej skrajnej sytuacji tego typu, można zdecydować się trwać bardzo ogólne podejście i dać użytkownikom końcowym ogólny mechanizm „okablowanie up” z obiektu-wykres ich wyboru, a nawet pozwolić im , aby zapewnić konkretne realizacje interfejsów do środowisko uruchomieniowe! (Twoja dokumentacja jest lśniącym klejnotem, użytkownicy są bardzo inteligentni, znają co najmniej gruboziarnisty zarys grafu obiektowego aplikacji, ale nie mają przydatnego kompilatora). Ten scenariusz może teoretycznie wystąpić w niektórych sytuacjach „korporacyjnych”.
W takim przypadku prawdopodobnie masz deklaratywny język, który pozwala użytkownikom wyrażać dowolny typ, kompozycję grafu obiektowego takich typów oraz paletę interfejsów, które mityczny użytkownik końcowy może mieszać i dopasowywać. Aby zmniejszyć obciążenie poznawcze użytkowników, wolisz podejście „konfiguracja zgodnie z konwencją”, tak aby musieli tylko wkroczyć i przejechać interesujący fragment wykresu obiektowego, zamiast zmagać się z całością.
Ty biedny darni!
Ponieważ nie masz ochoty pisać tego wszystkiego samemu (ale poważnie, sprawdź powiązanie YAML dla swojego języka), używasz pewnego rodzaju frameworku DI.
W zależności od dojrzałości tego frameworka, możesz nie mieć opcji użycia wstrzykiwania przez konstruktora, nawet jeśli ma to sens (kolaboranci nie zmieniają się przez cały czas istnienia obiektu), zmuszając w ten sposób do użycia Settera Injection (nawet gdy współpracownicy nie zmieniają się przez cały czas istnienia obiektu, a nawet jeśli nie ma tak naprawdę logicznego powodu, dla którego wszystkie konkretne implementacje interfejsu muszą mieć współpracowników określonego typu). Jeśli tak, to obecnie znajdujesz się w piekle silnie sprzężonym, pomimo starannego „wykorzystywania interfejsów” w całej bazie kodu - horror!
Mamy jednak nadzieję, że użyłeś frameworka DI, który daje ci możliwość wstrzyknięcia konstruktora, a twoi użytkownicy są trochę zrzędliwi, że nie spędzasz więcej czasu na zastanawianiu się nad konkretnymi rzeczami, których potrzebowali do skonfigurowania i nadaniu im interfejsu bardziej odpowiedniego do zadania na dłoni. (Chociaż, żeby być uczciwym, prawdopodobnie próbowałeś wymyślić jakiś sposób, ale JavaEE Cię zawiodło i musiałeś uciekać się do tego okropnego włamania).
Bootnote
Nigdy nie używasz Google Guice, co daje koderowi sposób na zrezygnowanie z tworzenia wykresu obiektowego z kodem ... przez pisanie kodu. Argh!