Dlaczego wzorzec projektowania metod fabrycznych jest bardziej przydatny niż posiadanie klas i wywoływanie ich indywidualnie?

32

Z wzorców projektowych „Gang of Four” jest metoda Factory:

class Factory(product)
  case product
  when a
    new A
  when b
    new B
  when c
    new C
end

new Factory(a)

Dlaczego jest to bardziej przydatne niż o trzech klasach a, boraz ci nazywając je indywidualnie?

alt
źródło
1
Co dokładnie masz na myśli? Dlaczego nie utworzyć wystąpienia wszystkich trzech? Czy o to Ci chodziło?
Neil
1
@Neil Nie, we wzorcu fabrycznym wszystkie klasy istnieją jako rodzeństwo. Po co dzwonić do fabryki, aby pośrednio uzyskać dostęp do klas a, b, c?
alt
3
tak naprawdę nie wygląda mi to na wzorzec metody fabrycznej, jeśli cokolwiek jest bliżej abstrakcyjnej fabryki
jk.
2
Ponieważ w czasie projektowania nie wiesz, którą z 3 klas musisz utworzyć.
MrWhite
2
@jk: Nie, tak naprawdę nie. programmers.stackexchange.com/questions/81838/…
pdr

Odpowiedzi:

54

Ponieważ twój przykład nie jest wystarczająco skomplikowany. W przypadku tak prostego scenariusza nie ma nawet sensu stosowanie zaawansowanego wzorca.

Ale jeśli musisz wiedzieć więcej niż produkt, aby zbudować A, B lub C, i nie możesz mieć bezpośredniego dostępu do tej wiedzy, to jest to przydatne. Następnie wykorzystujesz fabrykę jako centrum wiedzy do produkcji potrzebnych przedmiotów.

Być może te obiekty potrzebują odniesienia do jakiegoś obiektu X, który może dostarczyć fabryka, ale twój kod w miejscu, w którym chcesz zbudować A, B lub C, nie może lub nie powinien mieć dostępu do X. Może gdy masz X tworzysz A i B, ale jeśli masz typ Y, to tworzysz C.

Weź również pod uwagę, że niektóre obiekty mogą wymagać 20 zależności do utworzenia; co wtedy? Problemem może być polowanie na te zależności w miejscu, w którym nie powinny być one dostępne.

Mateusz
źródło
13
+1 za wyjaśnienie, że wzór fabryczny nie zawsze jest najlepszym podejściem.
Neil
1
Ponieważ twój przykład nie jest wystarczająco skomplikowany. W przypadku tak prostego scenariusza nie ma nawet sensu stosowanie zaawansowanego wzorca. Co byś zrobił w tym przypadku? Wstawić konstrukcję warunkową?
pdr
Może to być tylko metoda, która pobiera produkt i zwraca to, czego potrzebujesz, aby można go było ponownie wykorzystać, więc nie musi być wbudowany. Jeśli taka metoda wyrasta na coś większego lub jest stosowana w kilku innych klasach, możesz ją refaktoryzować do innej klasy.
Mateusz
Wzorzec nazywa się z tego powodu metodą fabryczną. Metoda nie musi należeć do innej klasy, aby była Metodą Fabryczną (choć często jest).
pdr
Brakowało mi w nim „Metody”, więc masz rację.
Mateusz
23

Wzorzec fabryczny jest zwykle bardziej złożony. Fabryka decyduje o określonych kryteriach, które wystąpienie utworzyć / zwrócić. Zamiast tego, gdy nie korzystasz z fabryki, kod ten będzie wielokrotnie używany w kilku lokalizacjach w kodzie.

Jako przykład rozważ następujące kwestie: musisz załadować dane z DB, ale masz jeden centralny DB do integracji z dużą ilością danych i jeden mniejszy w pamięci na każdym dev-PC. W kodzie pytasz fabrykę dostać się DB-uchwyt i powraca fabrycznych jedną z tych, w zależności od np plik konfiguracyjny.

Andy
źródło
20

Wzorzec metody fabrycznej wyodrębnia proces decyzyjny z klasy wywołującej. Ma to kilka zalet:

Ponowne użycie. Jeśli chcę utworzyć instancję w wielu miejscach, nie muszę powtarzać mojego warunku, więc kiedy przychodzę dodać nową klasę, nie ryzykuję, że ją pominę.

Testowalność jednostkowa. Mogę napisać 3 testy dla fabryki, aby upewnić się, że zwraca prawidłowe typy we właściwych warunkach, wtedy moja klasa wywołująca musi zostać przetestowana, aby sprawdzić, czy wywołuje fabrykę, a następnie wymagane metody na zwróconej klasie. Nie musi nic wiedzieć o realizacji samej fabryki ani konkretnych klasach.

Rozciągliwość. Gdy ktoś decyduje, że musimy dodać nową klasę D do tej fabryki, nigdy nie trzeba mówić o żadnym kodzie wywołującym, ani testach jednostkowych, ani implementacji. Po prostu tworzymy nową klasę D i rozszerzamy naszą metodę fabryczną. To jest właśnie definicja zasady otwartego i zamkniętego .

Możesz nawet utworzyć nową klasę fabryczną i sprawić, by były wymienialne podczas pracy, jeśli sytuacja tego wymaga - na przykład, jeśli chcesz mieć możliwość włączania i wyłączania klasy D podczas testowania. Natrafiłem na tę sytuację tylko raz, ale była ona bardzo przydatna.

Jak już powiedziano, Wzorzec Fabryczny nie zawsze jest właściwą drogą. Ale gdziekolwiek zobaczysz warunkową instancję, powinieneś się nad tym zastanowić.

pdr
źródło
14

Kluczowe zalety wzoru Factory są dwojakie:

  1. Miejsca, które wymagają wdrożenia produktu, nie muszą wiedzieć, jak je zbudować. Fabryka przechowuje te informacje.

    Czy chcesz wiedzieć, jakie argumenty przekazać konkretnemu konstruktorowi? Lub jakie zależności musisz wprowadzić? Lub jak zarejestrować klasę implementacji w bazie danych po jej pełnej konfiguracji? Nie? Niech fabryka zajmie się tymi wszystkimi sprawami.

  2. Miejsca, które wymagają implementacji produktu, nie muszą wiedzieć w czasie opisu modułu (tj. W czasie kompilacji), jak nazywa się klasa implementacji.

    Dlatego anie trzeba mieć z tym nic wspólnego A; „co zbudować” można opisać w kategoriach pożądanych właściwości niefunkcjonalnych, a nie tylko samej nazwy. Jest to o wiele bardziej elastyczne.

Minusem jest to, że tam, gdzie wiesz, co zrobić i jak to zrobić, stajesz się bardziej złożony, gdy używasz fabryki. Rozwiązanie tego problemu jest proste: nie używaj fabryki, jeśli nie ma to sensu!

Donal Fellows
źródło
2

Chciałbym myśleć o wzorcach projektowych w kategoriach bycia „ludźmi”, a wzorce to sposoby, w jakie ludzie rozmawiają ze sobą.

Tak więc według mnie wzór fabryki jest jak agencja zatrudnienia. Masz kogoś, kto będzie potrzebował zmiennej liczby pracowników. Ta osoba może znać pewne informacje na temat zatrudnionych osób, ale to wszystko.

Kiedy potrzebują nowego pracownika, dzwonią do agencji zatrudnienia i mówią im, czego potrzebują. Teraz, aby faktycznie kogoś zatrudnić, musisz wiedzieć wiele rzeczy - korzyści, weryfikację uprawnień itp. Ale osoba zatrudniająca nie musi nic o tym wiedzieć - agencja rekrutacyjna zajmuje się tym wszystkim.

W ten sam sposób korzystanie z fabryki pozwala konsumentowi tworzyć nowe obiekty bez konieczności poznawania szczegółów ich tworzenia ani zależności od nich - muszą jedynie podać informacje, których naprawdę potrzebują.

Kurtuazja

Premraj
źródło
1

Wzorzec fabryczny jest najbardziej nadużywanym i nadużywanym wzorem projektowym.

Natknąłem się na wiele przypadków, w których klasa Factory jest kodowana, gdy prosty konstruktor byłby odpowiedni.

Nie używaj klasy fabrycznej, chyba że:

  • Zależysz od zewnętrznego źródła, ale nie wiesz dokładnie, który z nich.
  • Budowa jest droga i chcesz ją zbudować raz i użyć wielokrotnie.
  • Konstruowanie nowej instancji zależy od tego, jakie instancje zostały już zbudowane (np. Twój może mieć tylko pięć połączeń, lub powinieneś użyć numeru identyfikacyjnego połączenia o jeden więcej niż ostatni użyty numer).
James Anderson
źródło
0

Użyj metody fabrycznej podczas tworzenia podklasy, a kod klienta nie powinien odpowiadać za podejmowanie decyzji, która konkretna podklasa jest tworzona.

Jest to użyteczne, ponieważ zapobiega konieczności zmiany kodu klienta, gdy trzeba zmienić typ instancji klasy. Zmiana istniejącego kodu jest złą praktyką, ponieważ zazwyczaj jest podatna na błędy.

Przykładem mogą być podklasy, w których każdy sortuje dane w porządku rosnącym, ale w inny sposób. Każdy sposób jest optymalny dla określonego rodzaju danych. np .: częściowo posortowane dane, dane, które są liczbami itp. Kod klienta to klasa, która obsługuje tylko drukowanie danych. Posiadanie kodu decydującego o tym, która klasa sortująca zostanie utworzona w klasie klienta, uczyniłaby ją złożoną klasą. Innymi słowy, ponosząc więcej niż jedną odpowiedzialność, w tym przypadku decyduje, która klasa sortowania jest optymalna i drukuje dane. Umieszczając kod decydujący o tym, która klasa sortująca zostanie utworzona w klasie Factory, rozdziela obawy, dzięki czemu nie trzeba zmieniać klasy klienta za każdym razem, gdy trzeba zmienić, która podklasa sortowania jest tworzona.

Jest to sposób na zakrycie twojego tyłka, jeśli możesz przewidzieć własne zmiany w sposobie tworzenia instancji klasy lub klasy, to warto zastosować klasy fabryczne. Pomaga skupić się na zajęciach na ich jednej odpowiedzialności, dzięki czemu mniej prawdopodobne jest, że będziesz musiał modyfikować istniejący niepowiązany kod.

kiwicomb123
źródło