Refaktoryzuję aplikację PHP i staram się mieć jak najwięcej zastrzyku zależności (DI).
Czuję, że dobrze rozumiem, jak to działa, i z pewnością widzę, że moje zajęcia stają się o wiele szczuplejsze i bardziej solidne.
Refaktoryzuję, aby móc wstrzykiwać zależność, zamiast tworzyć nowy obiekt w klasie, ale w pewnym momencie będę musiał utworzyć niektóre obiekty, to znaczy użyć przerażającego new
słowa kluczowego.
Problem, na który teraz natrafiłem, polega na tym, w którym momencie mogę rzeczywiście tworzyć nowe obiekty? Wygląda na to, że skończę w klasie najwyższego poziomu, tworząc mnóstwo nowych obiektów, ponieważ nie ma dokąd pójść. To źle.
Przeczytałem kilka blogów, które używają klas fabrycznych do tworzenia wszystkich obiektów, a następnie wstrzykujesz fabrykę do innych klas. Następnie możesz wywołać metody fabryczne, a fabryka utworzy dla ciebie nowy obiekt.
Moje obawy związane z robieniem tego są teraz, że moje zajęcia fabryczne będą new
darmowe dla wszystkich! Wydaje mi się, że może to być OK, ponieważ są to klasy fabryczne, ale czy są jakieś zasady, których należy przestrzegać, używając wzorca fabrycznego i DI, czy też odchodzę od tego znaku?
źródło
new
. Oczywiście istnieje kilka punktów wejścia, w których musisz zadzwonić do kontenera IoC, ale nie powinno ich być wiele. Zazwyczaj konfigurujesz IoC raz, a następnie poprosisz o rozwiązanie jednej klasy na żądanie. W przypadku MVC jest to zazwyczaj kontroler.Odpowiedzi:
Po dłuższej przeróbce wydaje się, że (jak wspomniano w komentarzu powyżej) klasa najwyższego poziomu, o której mówiłem, nazywa się Kompozycja Korzeń .
Rzeczywiście wydaje się, że jest to zaakceptowane rozwiązanie, aby dodać tworzenie wszystkich obiektów w tym składzie głównym (lub odwoływać się do kontenera IoC stąd).
Moim pierwotnym problemem było to, że ta klasa najwyższego poziomu byłaby trochę bałaganem. Jest to do pewnego stopnia prawdziwe, ale nasi profesjonaliści ważą wady. Na przykład widzę, że poprawiono czytelność, testowalność i łatwość konserwacji wszystkich innych klas.
Klasa najwyższego poziomu może być nieco niechlujna, zaśmiecona
new
i,set_property()
ale muszę powiedzieć, że wolę mieć cały ten kod w jednym miejscu, niż rozproszona po innych klasachKolejna przydatna strona omawiająca wyniki wydajności tej metody tutaj
źródło
Klasa Fabryki będzie
new
w nim zasypana. Byłoby to tworzenie dowolnego obiektu, o który prosisz, i prawdopodobnie zależności tego obiektu. Ponieważ zadaniem fabryk jest utworzenie odpowiedniego obiektu dla ciebienew
w tej klasie, nie jest złą rzeczą.DI jest tak, że masz luźno sprzężoną konstrukcję. Możesz wprowadzać zmiany w aplikacji, zmieniając zależność zapewnianą dla każdego obiektu. Dzięki temu Twoja aplikacja jest elastyczna, rozszerzalna i łatwa do przetestowania.
Na najwyższym poziomie będziesz mieć kod, który utworzy instancję kilku fabryk, skonfiguruje połączenia z usługami i wyśle odpowiedź. Będzie zawierał sporo
new
wywołań statycznych w celu utworzenia instancji obiektów niezbędnych dla twojej aplikacji. To właśnie tam należy.źródło
Moje dwa centy tutaj:
Nie określasz, czy używasz struktury wstrzykiwania zależności. Myślę, że zdecydowanie powinieneś. Użyj czegoś, co daje ci potrzebne funkcje: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .
Zwykle używasz konfiguracji lub centralnego punktu do tworzenia instancji początkowych obiektów tworzących twoją aplikację. Kontener stworzy dla ciebie obiekty.
Następnie uzyskujesz dostęp do obiektów (usług, dostawców, kontrolerów ...) za pośrednictwem kontenera IoC. W razie potrzeby w przejrzysty sposób utworzy dla Ciebie obiekt lub poda odniesienie do odpowiedniej istniejącej instancji.
Oczywiście wewnątrz konkretnej implementacji obiektów możesz tworzyć instancje innych obiektów, na których nie potrzebujesz DI (struktury danych, typy niestandardowe itp.), Ale to normalne programowanie.
Zwykle używasz fabryki, jeśli chcesz, aby środowisko IoC tworzyło niektóre obiekty IoC w twoich fabrykach (jest to potrzebne, gdy tworzenie konkretnego obiektu wymaga dodatkowej pracy). Jeśli możesz po prostu utworzyć swoje obiekty za pomocą „new Object ()” i ustawić niektóre właściwości, niekoniecznie chcesz użyć wzorca fabrycznego.
Innymi słowy, powiedziałbym, że użycie wzorca Factory dla klasy lub grupy klas zależy od tego, jak chcesz modelować te klasy, a nie od tego, czy używasz DI (chyba że twoja implementacja DI wyraźnie wymaga fabryk, co jest niezwykłe).
Skonfigurujesz również swoją strukturę IoC, aby korzystać z fabryki, gdy korzystasz z biblioteki innej firmy, która już wymaga użycia fabryki. W takim przypadku nie masz nad tym kontroli i musisz powiedzieć swojemu kontenerowi IoC: „hej, kiedy proszę o jeden z tych interfejsów, musisz skorzystać z tej fabryki, aby zapewnić mi odpowiednią instancję”.
W tym przypadku wydaje się, że nie musisz używać wzorców fabrycznych dla tych obiektów / usług / kontrolerów / czegokolwiek, i możesz po prostu skonfigurować IoC, aby utworzyć instancję z „nową” odpowiednią klasą i wstrzyknąć wszystko inne.
Mam nadzieję, że to pomoże.
źródło
doing DI manually beats the whole purpose of using an Inversion of Control container
- Jeśli przez to rozumiesz „... który centralizuje twoje zależności w pliku konfiguracyjnym”, to masz rację, ponieważ tak naprawdę to wszystko robi kontener IoC. Prawdziwym celem DI jest odsprzęganie i możesz to zrobić, podając swoje zależności w metodzie konstruktora. W tym celu wcale nie potrzebujesz frameworka DI.