Design patterns: Builder

1 minute read

Wzorzec kreacyjny który pozwala na tworzenie skomplikowanych obiektów krok po kroku. Wykorzystując Builder możemy uzyskać różne warianty i reprezentacje obiektu używając powtarzalnych fragmentów kodu do jego konstrukcji.

Podstawowym założeniem wzorca Builder jest przeniesienie kodu odpowiedzialnego za konstrukcje obiektu z jego pierwotnej klasy do odrębnych obiektów zwanych budowniczymi (ang. builders). Wspomniane obiekty organizują “składanie” obiektu w zbiór kroków (metod). Następnie w celu stworzenia wybranego wariantu obiektu wywołujemy kolejne kroki na obiekcie Builder. Nie musimy wykonywać wszystkich zdefiniowanych kroków, a tylko te prowadzące do oczekiwanego rezultatu. Niektóre kroki konstrukcyjne mogą wymagać innej implementacji w zależności od tego który wariant budujemy, w tym przypadku możemy stworzyć kilka klas Builder które implementują ten sam zbiór metod, każda na swój sposób.

Dodatkowym krokiem który możemy podjąć w ramach wzorca Builder jest stworzenie klasy Director. Jej zadaniem jest wykonanie serii kroków na klasie Builder w zdefiniowanej wcześniej kolejności. Klasa ta nie jest wymagana do działania wzorca, ale pomaga w uporządkowaniu powtarzalnych algorytmów tworzenia obiektu i ich użycia w różnych miejscach aplikacji. Zamiast za każdym razem wywoływać te samą serie metod, używamy jednej metody Directora przekazując mu odpowiedni Builder.

Zalety i wady:

  • Możliwość tworzenia obiektów krok po kroku, opóźnienia kroków konstrukcji i uruchamiania kroków rekursywnie.
  • Możliwość użycia tego samego kodu przy budowaniu różnych wersji obiektu.
  • Single Responsibility Principle. Izolacja skomplikowanego kodu konstrukcji obiektu od logiki biznesowej.

  • Złożoność kodu wzrasta ponieważ wzorzec wymaga stworzenia kilku dodatkowych klas.

Sposób implementacji:

  1. Upewnij się że możesz jasno zdefiniować wspólne kroki dla tworzenia każdego z wariantów obiektu. W przeciwnym wypadku nie będziesz w stanie zaimplementować wzorca.
  2. Zadeklaruj wszystkie kroki w interfejsie Builder.
  3. Implementując interfejs builder dodaj klasy Builder tworzące konkretne warianty i zaimplementuj kroki ich tworzenia. Pamiętaj o implementacji metody zwracającej stworzony obiekt. Metoda ta nie może być zdefiniowana w interejsie Builder ponieważ implementujące go klasy mogą w rezultacie tworzyć obiekty różnych typów, co oznacza że nie możemy przewidzieć typu obiektu zwracanego przez metode.
  4. Rozważ stworzenie klasy Director. Pozwala ona zdefiniować przepisy tworzenia różnych obiektów wykorzystując ten sam Builder.
  5. Aplikacja tworzy obiekty Builder oraz Director. Przed wywołaniem kroków tworzenia obiektu, aplikacja musi przekazać obiekt Builder do Directora. Możesz również tworzyć obiektu pomijając strukture Director, aby uzyskać nietypowy rezultat.
  6. Aplikacja powinna pozyskiwać stworzony obiekt bezpośrednio z klasy Buildera, chyba że wszystkie możliwe finalne produkty implementują ten sam interfejs - wtedy może zwracać go Director.

Przykładowy kod: [github]

Powiązane wzorce: Factory Method Composite Bridge