Wzorce projektowe (2)

Autor: Damian Chodorek • Opublikowany: 20 lipca 2015 • Kategoria: kursy, wzorce projektowe

Budowniczy.

Budowniczy to wzorzec obiektowy. Jego celem jest rozdzielenie tworzenia obiektów od ich reprezentacji. Budowniczy zazwyczaj stosowany jest do konstrukcji obiektów złożonych z innych obiektów, których inicjalizacja i konfiguracja jest wieloetopowa. Klient (programista korzystający z wzorca) dostaje obiekt stworzony przez budowniczego, gdy jest już gotowy i skonfigurowany

Klasy:

class Product{/*
klasa finalnego obiektu, który chcemy uzyskać
*/};

class Builder{/*
abstrakcyjna klasa budowniczego definiująca metody czysto wirtualne
*/};

class ConcreteBuilder: public Builder{/*
ustawia konkretne cechy produktu podczas jego tworzenia
*/};

class Director{/*
klient komunikuje się tylko z obiektem tej klasy, przekazuje mu budowniczego i otrzymuje gotowy produkt
*/};

Etapy działania:

  1. Klient konstruuje obiekt budowniczego.
  2. Klient konstruuje nadzorcę i przekazuje mu referencję do obiektu budowniczego.
  3. Klient zleca nadzorcy konstrukcję obiektu.
  4. Nadzorca zleca budowniczemu wykonanie odpowiednich działań.
  5. Klient pobiera gotowy produkt od nadzorcy.

Konsekwencje

Zalety:

  • większa kontrola tworzenia obiektu,
  • dodawanie nowych reprezentacji obiektów jest uproszczone,
  • zapobiegniecie duplikacji kodu odpowiedzialnego za tworzenie obiektów.

Wady:

  • duża liczba obiektów reprezentująca konkretne produkty.

Przykład

#include <iostream>
#include <string>

// Product
class Pizza
{
private:
    std::string dough;
    std::string sauce;
    std::string topping;

public:
    Pizza() { }
    ~Pizza() { }

    void SetDough(const std::string& d) { dough = d; };
    void SetSauce(const std::string& s) { sauce = s; };
    void SetTopping(const std::string& t) { topping = t; }

    void ShowPizza()
    {
        std::cout << " Yummy !!!" << std::endl
        << "Pizza with Dough as " << dough
        << ", Sauce as " << sauce
        << " and Topping as " << topping
        << " !!! " << std::endl;
    }
};

// Abstract Builder
class PizzaBuilder
{
protected:
    Pizza* pizza;
public:
    PizzaBuilder() {}
    virtual ~PizzaBuilder() {}
    Pizza* GetPizza() { return pizza; }

    void createNewPizzaProduct() { pizza =new Pizza(); }

    virtual void buildDough()=0;
    virtual void buildSauce()=0;
    virtual void buildTopping()=0;

};

// ConcreteBuilder
class HawaiianPizzaBuilder : public PizzaBuilder
{
public:
    HawaiianPizzaBuilder() : PizzaBuilder() {}
    ~HawaiianPizzaBuilder(){}

    void buildDough() { pizza->SetDough("cross"); }
    void buildSauce() { pizza->SetSauce("mild"); }
    void buildTopping() { pizza->SetTopping("ham and pineapple"); }
};

// ConcreteBuilder
class SpicyPizzaBuilder : public PizzaBuilder
{
public:
    SpicyPizzaBuilder() : PizzaBuilder() {}
    ~SpicyPizzaBuilder() {}

    void buildDough() { pizza->SetDough("pan baked"); }
    void buildSauce() { pizza->SetSauce("hot"); }
    void buildTopping() { pizza->SetTopping("pepperoni and salami"); }
};

// Director
class Waiter
{
private:
    PizzaBuilder* pizzaBuilder;
public:
    Waiter() : pizzaBuilder(NULL) {}
    ~Waiter() { }

    void SetPizzaBuilder(PizzaBuilder* b) { pizzaBuilder = b; }
    Pizza* GetPizza() { return pizzaBuilder->GetPizza(); }
    void ConstructPizza()
    {
        pizzaBuilder->createNewPizzaProduct();
        pizzaBuilder->buildDough();
        pizzaBuilder->buildSauce();
        pizzaBuilder->buildTopping();
    }
};


// A customer ordering two pizzas.
int main()
{
    Waiter waiter;

    HawaiianPizzaBuilder hawaiianPizzaBuilder;
    waiter.SetPizzaBuilder (&hawaiianPizzaBuilder);
    waiter.ConstructPizza();
    Pizza* pizza = waiter.GetPizza();
    pizza->ShowPizza();

    delete(pizza);

    SpicyPizzaBuilder spicyPizzaBuilder;
    waiter.SetPizzaBuilder(&spicyPizzaBuilder);
    waiter.ConstructPizza();
    pizza = waiter.GetPizza();
    pizza->ShowPizza();

    delete(pizza);

    return 0;
}

Źródło: https://sourcemaking.com/design_patterns/builder/java/2.

część 3

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.