Mam więc fabrykę, która tworzy obiekty różnych klas. Wszystkie możliwe klasy pochodzą od abstrakcyjnego przodka. Fabryka ma plik konfiguracyjny (składnia JSON) i decyduje, którą klasę utworzyć, w zależności od konfiguracji użytkownika.
Aby to osiągnąć, fabryka używa boost :: property_tree do parsowania JSON. Przechodzi przez ptree i decyduje, który konkretny obiekt stworzyć.
Jednak obiekty produktu mają wiele pól (atrybutów). W zależności od konkretnej klasy obiekt ma około 5-10 atrybutów, w przyszłości może nawet więcej.
Nie jestem więc pewien, jak powinien wyglądać konstruktor obiektów. Mogę wymyślić dwa rozwiązania:
1) Konstruktor produktu oczekuje każdego atrybutu jako parametru, dlatego konstruktor otrzyma ponad 10 parametrów. Będzie to brzydkie i doprowadzi do długich, nieczytelnych linii kodu. Zaletą jest jednak to, że fabryka może przeanalizować JSON i wywołać konstruktor z poprawnymi parametrami. Klasa produktu nie musi wiedzieć, że została utworzona z powodu konfiguracji JSON. Nie musi wiedzieć, że w ogóle jest zaangażowany JSON lub konfiguracja.
2) Konstruktor produktu oczekuje tylko jednego argumentu, obiektu property_tree. Następnie może przeanalizować potrzebne informacje. Jeśli brakuje informacji w konfiguracji lub jest ona poza zakresem, każda klasa produktu może zareagować poprawnie. Fabryka nie musi wiedzieć, jakich argumentów potrzebuje kilka produktów. Fabryka nie musi także wiedzieć, jak zareagować w przypadku nieprawidłowej konfiguracji. Interfejs konstruktora jest zunifikowany i mały. Jednak wadą jest, że produkt musi wyodrębnić potrzebne informacje z JSON, dlatego wie, jak jest skonstruowany.
Wolę rozwiązanie 2). Nie jestem jednak pewien, czy jest to dobry wzór fabryczny. Wydaje się, że to źle, informując produkt, że został utworzony w konfiguracji JSON. Z drugiej strony nowe produkty można wprowadzać bardzo prosto.
Jakieś opinie na ten temat?
Odpowiedzi:
Nie zrobiłbym opcji 2, ponieważ wtedy na zawsze rozwinęłeś konstrukcję swojego obiektu za pomocą analizy drzewa właściwości doładowania. Jeśli czujesz się komfortowo z klasą, która potrzebuje tak wielu parametrów, powinieneś czuć się komfortowo z konstruktorem, który potrzebuje tak wielu parametrów, takie jest życie!
Jeśli twoją główną troską jest czytelność kodu, możesz użyć wzorca konstruktora, jest to zasadniczo stopgap c ++ / java z powodu braku nazwanych argumentów. W efekcie powstają rzeczy, które wyglądają tak:
Więc teraz MyObject będzie miał prywatnego konstruktora, który zostanie wywołany w Builder :: build. Zaletą jest to, że będzie to jedyne miejsce, w którym będziesz musiał wywołać konstruktora z 10 parametrami. Fabryka drzewa właściwości doładowania użyje konstruktora, a następnie, jeśli chcesz zbudować MyObject bezpośrednio lub z innego źródła, przejdziesz przez konstruktora. Konstruktor zasadniczo pozwala wyraźnie nazwać każdy parametr podczas przekazywania, dzięki czemu jest bardziej czytelny. To oczywiście dodaje trochę podstawki, więc będziesz musiał zdecydować, czy warto, w porównaniu do zwykłego wywołania niechlujnego konstruktora lub zrzucenia niektórych istniejących parametrów do struktur itp. Po prostu rzucając inną opcję na stół.
https://en.wikipedia.org/wiki/Builder_pattern#C.2B.2B_Example
źródło
NIE używaj drugiego podejścia.
Z pewnością nie jest to rozwiązanie i prowadziłoby tylko do tworzenia instancji klas w logice biznesowej, zamiast do części aplikacji, w której znajdują się fabryki.
Zarówno:
O ile obiekt, który tworzysz, nie jest klasą odpowiedzialną za przechowywanie danych, powinieneś spróbować zmienić kod i podzielić dużą klasę na mniejsze.
źródło
new
lub konstruowania obiektów wewnątrz logiki biznesowej, nie jest to bardzo dobry projekt. Zobacz temat Nie szukaj rzeczy , który mówi Miško Hevery , który wyjaśnia bardziej szczegółowo, dlaczego wskazane przez ciebie podejście fabryczne jest złe zarówno z punktu widzenia testowania, jak i czytania. Ponadto twoja klasa wydaje się być obiektem danych, a dla tych na ogół dobrze jest mieć więcej parametrów niż zwykła klasa usług. Nie przejmowałbym się tym zbytnio.Opcja 2 jest prawie słuszna.
Ulepszona opcja 2
Utwórz klasę skierowaną do przodu, której zadaniem jest wzięcie tego obiektu JSON-struktury i wybranie bitów i wywołanie konstruktora (-ów) fabryki. Bierze to, co produkuje fabryka i przekazuje klientowi.
Zasadniczo „front end” mówi do 2 Bobs: „Mam do czynienia ze zredagowanymi klientami, więc inżynierowie nie muszą! Mam umiejętności ludzi!” Biedny Tom. Gdyby powiedział tylko: „Odłączam klienta od konstrukcji. To bardzo spójna fabryka”; mógł utrzymać swoją pracę.
Zbyt wiele argumentów?
Nie dla klienta - komunikacja front-end.
Front - fabryka? Jeśli nie 10 parametrów, najlepiej możesz odłożyć rozpakowywanie, jeśli nie oryginalna rzecz JSON, to trochę DTO. Czy to lepsze niż przekazanie JSON do fabryki? Tę samą różnicę mówię.
Zdecydowanie rozważyłbym przekazanie poszczególnych parametrów. Trzymaj się celu, jakim jest czysta, spójna fabryka. Unikaj obaw związanych z odpowiedzią @DavidPacker.
Łagodzenie „zbyt wielu argumentów”
Konstruktorzy fabryki lub klasy
Grupowanie argumentów interfejsu użytkownika
źródło