Builder design pattern: po co nam dyrektor?

[9]} ostatnio natknąłem się na wzór konstruktora. Wydaje się, że różni autorzy używają "Builder pattern", aby odnieść się do różnych smaków, więc pozwólcie, że opiszę wzór, o który pytam.

Mamy algorytm tworzenia produktów , czyli obiektów różnego typu. Na wystarczająco wysokim poziomie abstrakcji algorytm jest taki sam dla wszystkich typów produktów, ale każdy typ produktu wymaga innej implementacji każdego z abstrakcyjnych kroków algorytmu. Na przykład, możemy mieć następujący algorytm pieczenia ciast:

 1. Add liquids.
 2. Mix well.
 3. Add dry ingredients.
 4. Mix well.
 5. Pour batter into baking pan.
 6. Bake.
 7. Return baked cake.

Różne ciasta wymagałyby różnych implementacji tych kroków, tj. jakich płynów/suchych składników użyć, z jaką prędkością mieszać, jak długo piec, itp.

Wzór mówi, aby zrobić to w ten sposób. Dla każdego produktu tworzymy klasę concrete builder z implementacją dla każdego z powyższych kroków. Wszystkie te klasy pochodzą z klasy bazowej abstract builder, która jest zasadniczo interfejs. Tak więc, na przykład, będziemy mieli abstrakcyjną klasę bazową CakeBaker z czystymi metodami wirtualnymiAddLiquid(), MixLiquids(), itd. Betonowe wypieki będą betonowymi podklasami, np.

class ChocolateCakeBaker : public CakeBaker {
public:
   virtual void AddLiquids()
   {
        // Add three eggs and 1 cup of cream
   }

   virtual void AddDryIngredients()
   {
       // Add 2 cups flour, 1 cup sugar, 3 tbsp cocoa powder,
       // 2 bars ground chocolate, 2 tsp baking powder
   }
      ...
      ...
};

LemonCitrusCakeBaker byłaby również podklasą CakeBaker, ale używałaby różnych składników i ilości w swoich metodach.

Różne typy ciastek będą podobnie podklasami abstrakcyjnej klasy bazowej Cake.

Wreszcie, mamy klasę do implementacji abstrakcyjnego algorytmu. To jest dyrektor . W przykładzie piekarni możemy go nazwać ExecutiveBaker. Klasa ta zaakceptowałaby (od klienta) konkretny obiekt konstruktora i użyłaby jego metod w celu utworzenia i zwrócenia pożądanego produktu.

Oto moje pytanie. Dlaczego reżyser musi być oddzielony od abstrakcyjnego budowniczego? Dlaczego nie przetworzyć ich do jednej abstrakcyjnej klasy bazowej Buildera, aby zabezpieczyć publiczne metody oryginalnego abstrakcyjnego budowniczego (a konkretne podklasy nadpisują je jako przed).
Author: Micha Wiedenmann, 2010-11-30

7 answers

Podstawowa część wzoru Builder dotyczy abstrakcyjnego Buildera i jego podklas (betonowych budowniczych). Zgodnie z wzorcami projektowymi GoF dyrektor po prostu "powiadamia konstruktora, gdy część produktu powinna zostać zbudowana", co może być doskonale wykonane przez Klienta.

Klasa StringBuilder W API Java jest przykładem konstruktora bez odpowiedniego dyrektora-zazwyczaj Klasa klienta "kieruje" go.

Również w skuteczny Java i Tworzenie i niszczenie obiektów Java , Joshua Bloch sugeruje użycie wzorca builder i nie zawiera dyrektora.

 19
Author: izilotti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-14 20:00:14

Jeśli rozdzielisz na Director I Builder, udokumentowałeś różną odpowiedzialność za montaż produktu od zestawu części (director) i odpowiedzialność za tworzenie części (builder).

  • w builderze możesz zmienić sposób budowania części. W Twoim przypadku, Czy AddLiquid() należy dodać śmietanę lub mleko.
  • w reżyserze możesz zmienić sposób montażu części. W Twoim przypadku a używając AddChocolate() zamiast AddFruits() otrzymujesz inny tort.

Jeśli chcesz tej dodatkowej elastyczności, zmieniłbym nazwę NA (ponieważ użycie baker w budowniczym sugeruje, że to zadanie budowniczych polegało na montażu części)

class LightBakingSteps : public BakingSteps {
public:
    virtual void AddLiquids()
    {
        // Add milk instead of cream
    }

    virtual void AddDryIngredients()
    {
        // Add light sugar
    }

    ...
};

class ChoclateCakeBaker : public CakeBaker {
public:
     Cake Bake(BakingSteps& steps)
     {
         steps.AddLiquieds();
         steps.AddChocolate();      // chocolate instead of fruits
         return builder.getCake();
     }
}
 9
Author: Micha Wiedenmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-06 09:55:15

Odmiana GoF wzoru Builder nie ma Builder bez Director. Jest w tym inny punkt, ale wyjaśnię dalej.

Wzorzec konstruktora ma dać Ci wiele sposobów na stworzenie tego samego obiektu. Builder powinien mieć tylko metody, które budują różne części obiektu, ale algorytm-sposób wykonywania tych funkcji-powinien być problemem Dyrektora. Bez Dyrektora każdy klient musiałby dokładnie wiedzieć, w jaki sposób budynek działa. Ale z dyrektorem wszystko, co klient musi wiedzieć, to jakiego konstruktora użyć w konkretnym przypadku.

Więc mamy tu dwie części:

  1. Builder, który tworzy części obiektu jeden po drugim. Ważne jest, aby pamiętać, że w tym celu zachowuje stan utworzonego obiektu.
  2. Dyrektorze, który kontroluje sposób wykonania Buildera.

Teraz do punktu, o którym mówiłem wcześniej. Część Builder wzoru jest przydatna w innych przypadkach i została użyta przez różnych sprzedawców bez dyrektora do różnych celów. Przykładem takiego zastosowania może być Doctrine Query Builder.

Wadą takiego podejścia jest to, że konstruktor zaczyna budować obiekt, który staje się stateful i jeśli Klient nie resetuje konstruktora po utworzeniu obiektu - inny klient lub ten sam klient, który był używany więcej niż raz, może uzyskać części obiektu, który został utworzony wcześniej. Z tego powodu Doktryna używa Wzorzec fabryczny do tworzenia każdej instancji konstruktora.

Mam nadzieję, że to pomoże tym googlującym.

 7
Author: drakonli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 20:38:46

Powiedzmy, że chcesz zrobić ciasto bez suchych składników. To, co zrobisz, to dodanie nowej metody do reżysera lub mianowanie innego reżysera. To ochroni Cię przed złożonością dziedziczenia, a także sprawi, że Twój kod będzie bardziej elastyczny.

 2
Author: Mahmoud abdelsalam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-16 19:57:10

Zgadzam się z Tobą. Myślę, że innym podejściem jest to, że CakeBaker powinien mieć metodę GetCake (), która zwraca metodę cake(Klasa Cake) i MakeCake (), w której algorytm będzie działał. To dobrze, ale z drugiej strony jest tam odpowiedzialna separacja. Rozważ abstrakcyjnego budowniczego i konkretne buldery jako budowniczych części ciasta tylko i dyrektor jako kierownik lub projektant, którego zadaniem jest złożenie i wyprodukowanie ciasta.

 0
Author: Arseny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-30 13:00:20

Konstruktor wie, jak wykonać określone kroki. Reżyser wie, jak zmontować całość za pomocą kroków konstruktora.

Pracują razem.

Jedyną kruchością, jaką widzę w tym wzorze, jest to, że klient jest w stanie wywoływać metody Builder bezpośrednio bez Director - co może powodować pewne problemy i niespójność (na przykład nie wywoływanie metody Init, która jest częścią całego algorytmu)

 0
Author: Aleksander Bethke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-14 15:53:11

Minusem wzorców jest to, że zanieczyszczają one nasze zrozumienie domeny biznesowej terminami technicznymi i zacierają nasze skupienie.

Jak widzę-jest zbyt wiele powiązań między ciastem a wiedzą, jak je zrobić. Można je oddzielić, wprowadzając pomysł, aby ciasto miało przepis w naszym kodzie (bardziej jak zapożyczenie z realnego świata, zaprojektowanie naszego modelu według domeny biznesowej). Przepis miałby składniki i etapy pieczenia (tylko nazwę kroku, a nie rzeczywistą realizację, ponieważ przepisy nie piecz ciast) jak zrobić ciasto co opisuje przepis. Nasz piekarz miałby metodę BakeCake( przepis) i kilka mniejszych metod zgodnie z krokami pieczenia, takich jak wymieszanie, dodanie składnika itp.

Pamiętaj, że jeśli będziesz musiał ogólnie modelować szefa kuchni, a nie tylko piekarza tortów, musisz również oddzielić wiedzę o robieniu wypieków od samego piekarza. Można to zrobić poprzez wprowadzenie idei kucharza posiadającego umiejętności.

 -1
Author: Arnis Lapsa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-06 16:19:42