Wzorzec Budowniczy (ang. Builder)

Przeznaczenie

Wzorzec ten oddziela konstrukcję obiektów złożonych od ich reprezentacji, umożliwiaj?c tym samym powstawanie w jednym procesie konstrukcyjnym różnych reprezentacji.
Przykład: Czytnik plików RTF.

Przykładem może być tutaj oprogramowanie konwertujące tekst z jednego formatu na drugi. Algorytm odczytujący i interpretujący dane wejściowe jest oddzielony od algorytmu tworzącego dane wyjściowe. Dzięki takiemu rozwiązaniu możemy stosować jeden obiekt odczytujący dane wejściowe oraz wiele obiektów zapisujących je w różnych formatach (ASCII, HTML, RTF, itp.)

Budowniczy jest to jeden z kreacyjnych wzorców projektowych (obiektowy), którego celem jest rozdzielenie sposobu tworzenia obiektów od ich reprezentacji. Dzięki takiemu rozwiązaniu w tym samym procesie konstrukcyjnym możemy tworzyć różne reprezentacje obiektów. Budowniczy różni się od wzorca fabryki abstrakcyjnej oraz pozostałych wzorców kreacyjnych tym, że skupia się na sposobie tworzenia obiektów reprezentujących produkty. Budowniczy tworzy drobną częśc skomplikowanego produkt za każdym swoim wywołaniem jednoczesnie kontrolując stan wykonanej pracy. Klient dostaje produkt po zakończeniu pracy Budowniczego a nie - tak jak w przypadku Fabryki abstrakcyjnej - "od razu".

Struktura


Jak widać na przedstawionym diagramie klas wzorzec składa się z dwóch podstawowych obiektów. Pierwsza z nich oznaczony jest jako Budowniczy - jego celem jest dostarczenie interfejsu do tworzenia produktów. Drugim obiektem jest obiekt oznaczony jako Konkretny Budowniczy a jego celem jest tworzenie konkretnych produktów korzystając z interfejsu obiektu Budowniczy. Strukturę wzorca uzupełnia obiekt Kierownika, wydaje on polecenia konstrukcji produktów wykorzystując do tego obiekt Budowniczego

Konsekwencje stosowania

Do plusów stosowania wzorca należą: duża możliwość zróżnicowania wewnętrznych struktur klas oraz możliwość kontrolowania tworzenia obiektów po stronie klienta. Minusem jest duża liczba obiektów reprezentujących konkretne produkty.

Uczestnicy

  • Budowniczy - określa interfejs abstrakcyjny do tworzenia części składowych obiektu Produkt.
  • BudowniczyKonkretny - konstruuje i zestawia części produktu poprzez implementowanie interfejsu Budowniczego; definiuje i kontroluje tworzoną przez siebie reprezentację;zapewnia interfejs do wyszukiwania produktu.
  • Kierownik - konstruuje obiekt, używając interfejsu Budowniczego.
  • Produkt - reprezentuje konstruowany obiekt złożony; Klasa BudowniczyKonkretny buduje wewnętrzną reprezentację produktu i definiuje proces składania go; zawiera klasy definiujące części składowe, włączając w to interfejsy zestawiania części w końcowy wynik.

Współpraca

  • Klient tworzy obiekt Kierownik i konfiguruje go za pomocą pożądanego obiektu Budowniczy.
  • Kierownik informuje budowniczego o potrzebie zbudowania części produktu.
  • Budowniczy przetwarza żądania kierownika i dodaje części do produktu.
  • Klient odbiera produkt od budowniczego.

Diagram sekwencji

Przykład

class Produkt
{
public:
  void dodajCzesc(std::string czesc) { /*...*/ }
};
class Budowniczy
{
public:
  void zbudujCzescA() = 0;
  void zbudujCzescB() = 0;
  Produkt pobierzWynik() = 0;
};
// buduje obiekt z czesci
class BudowniczyJakis : public Budowniczy
{
Produkt *produkt;
public:
  void zbudujCzescA()
  {
    czesc.dodajCzesc( "CzescA" );
  }
  void zbudujCzescB()
  {
    czesc.dodajCzesc( "CzescB" );
  }
  Produkt *pobierzWynik()
  {
    return produkt;
  }
};

class Dyrektor
{
public:
  void Konstruuj(Budowniczy *budowniczy)
  {
    budowniczy.zbudujCzescA();
    budowniczy.zbudujCzescB();
  }
};
// sposób wykorzystania
int main()
{
  Dyrektor *director = new Dyrektor();
  Budowniczy *builder = new BudowniczyJakis();
  Produkt *product;
  director.Konstruuj(builder);
  product = builder.pobierzWynik();
  /* ... */
}
Zobacz przykład