Organizacja kodu uchroni nas przed wieloma bólami. Używając cech programowania obiektowego, możemy zastosować pewne wzorce projektowe, aby osiągnąć lepszą czytelność, zredukować redundancję i stworzyć abstrakcje, jeśli jest to potrzebne. Jednym z takich wzorców jest wzorzec fabryki.
Wzorzec fabryki jest rodzajem wzorca Object Oriented, który podąża za metodologią DRY. Jak sama nazwa wskazuje, instancje obiektów są tworzone poprzez użycie fabryki, która wykona dla nas wymagany obiekt.
Przyjrzyjrzyjmy się bardzo prostemu przykładowi użycia wzorca fabryki do złożenia alligator
obiektu. Aby to zrobić, musimy najpierw stworzyć fabryki, które stworzą dla nas części alligator
:
class TailFactory { constructor(props) { this.tailLength = props.tailLength; }};class TorsoFactory { constructor(props) { this.color = props.color; }};class HeadFactory { constructor(props) { this.snoutLenth = props.snoutLenth; }};
Teraz tworzymy klasę, która działa jako pośrednik między rzeczywistymi klasami fabryk a użytkownikiem. Nazwijmy ją ReptilePartFactory
:
class ReptilePartFactory { constructor(type, props) { if(type === "tail") return new TailFactory(props); if(type === "torso") return new TorsoFactory(props); if(type === "head") return new HeadFactory(props); }};
Przejdźmy teraz do złożenia rzeczywistego aligatora i użyjmy ReptilePartFactory
, aby uzyskać dla nas wymagane części:
let alligator = {};let alligatorProps = { tailLength : 2.5, color: "green", snoutLenth: 1};//gets a tail from the tail factoryalligator.tail = new ReptilePartFactory("tail", alligatorProps); //gets a torso from the torso factoryalligator.torso = new ReptilePartFactory("torso", alligatorProps);//gets a head from the head factoryalligator.head = new ReptilePartFactory("head", alligatorProps);
Patrząc na powyższy wzór, wydaje się, że moglibyśmy użyć tego samego ReptilePartFactory
do tworzenia części dla obiektów podobnych do aligatora. Fabryki w tle nigdy nie musiałyby wiedzieć o naturze końcowego obiektu.
Tak więc, użycie wzorca fabryki daje nam pewne korzyści:
- Dynamiczne tworzenie obiektów: Może być stosowany w przypadkach, gdy typ obiektu jest ustalany w czasie wykonywania.
- Abstrakcja: Użytkownik nigdy tak naprawdę nie musi mieć dostępu do rzeczywistego konstruktora obiektu.
- Wielokrotne wykorzystanie/utrzymanie: Te same fabryki mogą być używane dla podobnych obiektów i pozwala nam to na łatwe dodawanie/usuwanie nowych klas obiektów bez zmiany dużej ilości kodu.
Teraz, gdy mamy już pewne zrozumienie wzorca fabryki, zbadajmy trochę na temat pisania lepszego kodu wzorca fabryki.
Powyższy przykład używa drabinki if-ladder, aby dowiedzieć się, którą fabrykę wywołać na podstawie danych wejściowych użytkownika. Jest to prosta implementacja, intuicyjna i niezbyt otwarta na zmiany. Jeśli mamy nowe części do dodania później, to musielibyśmy zaburzyć ReptilePartFactory
. Jest to pogwałcenie zasad SOLID, które mówią: „Elementy oprogramowania (klasy, moduły, funkcje, itp.) powinny być otwarte na rozszerzenie, ale zamknięte na modyfikację”.
A może przechowamy klasy fabryk w obiekcie i wywołamy żądaną fabrykę części używając części, którą chcemy jako klucz? Najpierw musielibyśmy zarejestrować fabryki, byłoby to tak proste jak:
let registeredPartFactories = {};registeredPartFactories = class TailFactory{ ...};registeredPartFactories = class TorsoFactory { ...};registeredPartFactories = class HeadFactory { ...};
A teraz, warstwa abstrakcyjna może wywoływać fabryki w ten sposób:
class ReptilePartFactory { constructor(type, props) { return new registeredPartFactories(props); }};
To podejście jest znacznie czystsze i pozwala na rozszerzenie naszych fabryk bez wpływu na kod w ReptilePartFactory
.
W podsumowaniu
Istnieje kilka innych wzorców obiektowych, które również zwiększają czytelność i jakość. Zanim więc użyjesz wzorca fabryki, sprawdź, czy istnieje dla niego prawdziwe wymaganie. Jeśli zamierzasz tworzyć podobne typy obiektów wielokrotnie, a także potrzebujesz warstwy do tworzenia nowych instancji przy użyciu tych obiektów, zapewniając jednocześnie pewien poziom abstrakcji do logiki tworzenia, to tak – wzorzec fabryki jest dobrym rozwiązaniem.