Modele de proiectare - Un ghid rapid pentru modelul Builder.

Modelul Builder este un model de design creațional care gestionează pas cu pas construcția de obiecte complexe (sau cărămidă cu cărămidă). Este probabil cel mai ușor model de detectat dacă codul existent are nevoie de un astfel de design. Modelul Builder permite crearea reprezentărilor diferite ale unui obiect folosind același cod de construcție.

Modelul de constructor este clasificat în tiparele de design creațional, care se referă la instanța de clasare / obiect Mai precis, modul de utilizare eficientă a moștenirii (tipare de creare a clasei) sau a delegării (modele de creare a obiectelor). [după modelele de design explicate simplu]

Exemplu: Să începem cu un exemplu pe tema mea preferată. Alimente!! Mai exact exemplul va fi despre pizza. Pizza este separată în trei straturi, aluatul, sosul și blaturile. Acum, să ne întrebăm, cum am „construi” un obiect de pizza selectând printre diferite toppinguri și o varietate de sosuri.

Întrebări înainte de a proiecta o soluție la această problemă:

  • Cum ar arăta constructorul clasei Pizza?
  • Ar trebui să avem mai mulți constructori de suprasarcină cu parametri pentru toate combinațiile precum sosuri, toppinguri, sosuri etc. Ce se întâmplă dacă avem și diferite tipuri de aluat?
  • Dacă mai târziu, vom decide să adăugăm brânză sau diferite tipuri de brânză? Ar fi ușor de pus în aplicare? Dar dependențele de codul existent?
  • Ar trebui să avem doar un constructor implicit care creează o „pizza simplă”? Nu ar fi obligat clientul să apeleze la un număr de setatori în consecință? Este sigur? Ce se întâmplă dacă clientul uită și atunci trimitem clientului o pizza simplă?

Soluția la toate aceste întrebări este modelul constructorului. Avem nevoie de un „constructor” pentru a construi o pizza pas cu pas. În același timp, clientul va fi în siguranță să „comande” o pizza specifică și îl va face pe constructor să o construiască pentru el.

Pasul 1 - Cuvinte cheie

  1. Reprezentare: Un obiect poate avea reprezentări diferite. De exemplu, o pizza poate avea toppinguri de mozzarella de roșii și o altă reprezentare a pizza ar fi cu ciuperci și șuncă de parma.
  2. Codul construcției: Obiectele pot fi construite în moduri diferite, de exemplu, utilizând constructori. Constructorii pot fi supraîncărcați, au același nume (numele clasei), dar un număr / tipuri de argumente diferite. În funcție de numărul și tipul de argumente transmise, se numește constructorul specific.

Este ușor să cadem în capcana de a avea o clasă de numeroși constructori în care fiecare ia un număr diferit de parametri. Dezvoltatorul este obligat să instantaneze clasa cu combinația corectă de parametri pentru fiecare situație. Această problemă are un nume, este un anti-model popular numit constructor telescopic și modelul de constructor este soluția ideală pentru aceasta. Să supradimensionăm modelul Builder spunând neclar:

Principala intenție a modelului Builder este de a avea un număr minim de constructori de supraîncărcare pentru a susține constuația mai multor reprezentări ale unui obiect.

Pasul 2 - diagrama (de exemplu)

Să rămânem la exemplul de pizza. Pe scurt, avem clasa de pizza, bucătarul și constructorii de beton care moștenesc de la constructorul abstract. Vom explica diagrama de jos în sus:

  • Pizza_Product: această clasă este pizza propriu-zisă. Este reprezentat de trei atribute: (1) Aluat, (2) sos și (3) toppinguri.
  • ConcreteBuilder: Fiecare constructor de beton este responsabil pentru o reprezentare specifică. În acest exemplu, avem Margherita și Spicy Pizza. Ambii constructori de beton sunt responsabili să „construiască” propria lor reprezentare a pizza pe baza celor trei atribute enumerate mai sus.
  • AbstractBuilder: conține o variabilă de membru pizza și constructorii de beton moștenesc de la ea.
  • Cook_Director: în acest exemplu, regizorul este bucătarul propriu-zis. Clasa este responsabilă să inițieze construcția unei reprezentări date, punând piesele împreună astfel încât constructorul să urmeze și să se adapteze în funcție de nevoile regizorului.

Pasul 3 - Cod de exemplu

V-aș sugera să copiați clasa de cod pe clasă din depozitul meu de git „Andreas Poyias” sau fragmentele de mai jos (în ordinea furnizată) și să-l lipiți în oricare dintre editorii C ++ online disponibili, cum ar fi c ++ shell, jdoodle, onlineGDBand rulați-l să observe ieșirea. Apoi citiți comentariile sau descrierea de mai jos. Luați timp citind-o în detaliu (asta înseamnă un minut, nu mai puțin și nu mai mult).

Produs:
Aceasta este clasa de pizza. Este o clasă simplă, cu trei setatori și o metodă gustativă, care tipărește toate ingredientele.

#include 
#include  // unique_ptr
folosirea spațiului de nume std;
clasa Pizza_Product
{
public:
 void setDough (const string & aluat) {m_dough = aluat; }
 void setSauce (const string & sos) {m_sauce = sos; }
 void setTopping (const string & topping) {m_topping = topping; }
gol gol () const
{
  cout << "Pizza cu" << m_dough << "aluat",
       << m_sauce << "sos și"
       << m_topping << "topping. Mmmmmmm." << endl;
}
privat:
 șir m_dough;
 șir m_sauce;
 string m_topping;
};

Abstract Builder:
Constructorul abstract este o interfață care conține un obiect pizza. Are un getter care returnează obiectul pizza și o metodă de a instaura obiectul pizza. De asemenea, acesta declară cele trei metode de construire care vor fi puse în aplicare de către constructori de beton mai jos.

clasa Pizza_Builder
{
public:
  virtual ~ Pizza_Builder () {};
  Pizza_Product * getPizza () {return m_pizza.release (); }
  void createNewPizzaProduct ()
  {
    m_pizza = make_unique  ();
  }
  virtual void buildDough () = 0;
  virtual void buildSauce () = 0;
  virtual void buildTop () = 0;
protejat:
  unique_ptr  m_pizza;
};

Constructori de beton:
Două exemple de constructori de beton și două reprezentări ale unei pizza. Amândoi implementează propriile lor metode de construire folosind obiectul m_pizza din clasa părinte (Abstract builder)

clasa Margherita_ConcreteBuilder: public Pizza_Builder
{
public:
 virtual void buildDough () {m_pizza-> setDough ("încrucișare"); }
 virtual void buildSauce () {m_pizza-> setSauce ("tomate"); }
 virtual void buildTop () {m_pizza-> setTopping ("mozzarela + busuioc"); }
};
clasa Spicy_ConcreteBuilder: public Pizza_Builder
{
public:
 virtual void buildDough () {m_pizza-> setDough ("pan baked"); }
 virtual void buildSauce () {m_pizza-> setSauce ("tomate + chilli"); }
 virtual void buildTop () {m_pizza-> setTopping ("pepperoni + salami"); }
};

Director:
Această clasă pune totul laolaltă. Are o variabilă Pizza_Builder. Folosește makePizza () pentru a primi un constructor de beton ca parametru. Apoi apelează operațiunile de compilare care funcționează în mod corespunzător pentru ambele reprezentări. Prin urmare, atingem scopul de a avea un cod de construcție care să reprezinte diferite tipuri de pizza. Metoda tastePizza () constă în tipărirea conținutului unei pizza.

clasă Cook_Director
{
public:
 void tastePizza () {m_pizzaBuilder-> getPizza () -> gust (); }
void makePizza (Pizza_Builder * pb)
 {
   m_pizzaBuilder = pb;
   m_pizzaBuilder-> createNewPizzaProduct ();
   m_pizzaBuilder-> buildDough ();
   m_pizzaBuilder-> buildSauce ();
   m_pizzaBuilder-> buildTop ();
 }
privat:
 Pizza_Builder * m_pizzaBuilder;
};

Principal (client):
 Metoda principală funcționează ca client (la fel ca ghidurile anterioare). Este atât de ușor pentru client să poată construi diferite reprezentări ale unei pizza. Avem nevoie de regizor și apoi, trecând doar doi constructori de beton diferiți ca parametru către themakePizza, vom putea să gâdilăm două tipuri diferite de pizza.

int principal ()
{
  Cook_Director bucătar;
  Margherita_ConcreteBuilder margheritaBuilder;
  Spicy_ConcreteBuilder picantPizzaBuilder;
  cook.makePizza (& margheritaBuilder);
  cook.tastePizza ();
  cook.makePizza (& spicyPizzaBuilder);
  cook.tastePizza ();
}
// Iesire
// Pizza cu aluat încrucișat, sos de roșii și mozzarela + topping de busuioc. // Mmmmmmm.
// Pizza cu aluat copt tigaie, roșii + sos și ardei iute
// toponie de piper + salam. Mmmmmmm.

Rezumăm avantajele acestui model:

  • Există multe reprezentări posibile, dar o singură intrare comună.
  • Avem un protocol standard pentru crearea tuturor reprezentărilor posibile. Etapele acestui protocol sunt expuse în mod clar de o interfață Builder.
  • Există o clasă concretă derivată pentru fiecare reprezentare țintă
  • Este ușor pentru un dezvoltator să adauge o nouă reprezentare de sine stătută și independentă (a unei pizza), fără teama de a rupe altceva.
  • Clientul poate doar să înregistreze ConcreteBuilder la Director și să obțină reprezentarea așteptată.

Următorul blog va fi un ghid rapid pentru modelul de design Decorator. Este un model structural care este obligatoriu pentru depozitul dvs. de cunoștințe. Nu uitați să-mi place / să aplaudați pe blogul meu și să urmați contul meu. Acest lucru înseamnă să-mi ofer satisfacția că am ajutat unii colegi dezvoltatori și să mă împing să continui să scriu. Dacă există un model de design specific despre care doriți să aflați, spuneți-mi în comentariile de mai jos, pentru a vă putea oferi în următoarele câteva săptămâni.

Alte ghiduri rapide privind modelele de proiectare:

  1. Modele de proiectare - Un ghid rapid pentru Abstract Factory.
  2. Modele de proiectare - Un ghid rapid pentru modelul Bridge.
  3. Modele de proiectare - Un ghid rapid pentru modelul Builder.
  4. Modele de proiectare - Un ghid rapid pentru modelul de decorare.
  5. Modele de proiectare - Un ghid rapid pentru modelul fațadelor.
  6. Modele de proiectare - Un ghid rapid pentru modelul de observare.
  7. Modele de proiectare - Un ghid rapid pentru modelul Singleton.