Menu
Coddy logo textTech

Wzorzec Builder

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 93 z 104.

Wzorzec Builder oddziela tworzenie złożonego obiektu od jego reprezentacji, umożliwiając tworzenie różnych konfiguracji krok po kroku. Jest to szczególnie przydatne, gdy obiekt ma wiele opcjonalnych parametrów lub wymaga określonej kolejności tworzenia.

Zamiast konstruktora z wieloma parametrami (co może być mylące) Builder udostępnia przejrzyste, nazwane metody dla każdej opcji konfiguracji:

#include <iostream>
#include <string>

class Pizza {
public:
    std::string dough;
    std::string sauce;
    std::string topping;
    bool cheese;
    
    void describe() const {
        std::cout << dough << " dough, " << sauce << " sauce, "
                  << topping << (cheese ? ", with cheese" : "") << "\n";
    }
};

class PizzaBuilder {
private:
    Pizza pizza;
    
public:
    PizzaBuilder& setDough(const std::string& d) {
        pizza.dough = d;
        return *this;
    }
    
    PizzaBuilder& setSauce(const std::string& s) {
        pizza.sauce = s;
        return *this;
    }
    
    PizzaBuilder& setTopping(const std::string& t) {
        pizza.topping = t;
        return *this;
    }
    
    PizzaBuilder& addCheese() {
        pizza.cheese = true;
        return *this;
    }
    
    Pizza build() { return pizza; }
};

int main() {
    Pizza margherita = PizzaBuilder()
        .setDough("thin")
        .setSauce("tomato")
        .setTopping("basil")
        .addCheese()
        .build();
    
    margherita.describe();
}

Każda metoda ustawiająca zwraca referencję do konstruktora (return *this), umożliwiając łączenie metod w płynny interfejs. Metoda build() finalizuje i zwraca skonstruowany obiekt.

Użyj wzorca Builder podczas konstruowania obiektów z wieloma opcjonalnymi komponentami, gdy chcesz, aby kod tworzący obiekty był czytelny, lub gdy ten sam proces tworzenia powinien tworzyć różne reprezentacje.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system Computer Builder, który pozwala użytkownikom krok po kroku konfigurować niestandardowe komputery. To idealny przypadek do zastosowania wzorca Builder: komputery mają wiele opcjonalnych komponentów, a nam zależy na przejrzystym i czytelnym sposobie składania różnych konfiguracji.

Podzielisz kod na trzy pliki:

  • Computer.h: Zdefiniuj klasę produktu reprezentującą w pełni skonfigurowany komputer.

    Twoja klasa Computer powinna przechowywać następujące komponenty jako prywatne składowe: cpu (string), ram (string), storage (string), gpu (string) oraz hasWifi (boolean). Domyślnie inicjalizuj hasWifi wartością false, a ciągi znaków pustymi wartościami.

    Dodaj publiczną metodę o nazwie showSpecs(), która wyświetla konfigurację komputera. Dla każdego ustawionego komponentu (niepustego ciągu znaków) wypisz go w osobnym wierszu. Możliwość korzystania z Wi-Fi powinna być wyświetlana tylko wtedy, gdy jest włączona.

  • ComputerBuilder.h: Utwórz klasę budującą komputery za pomocą płynnego interfejsu.

    Twoja klasa ComputerBuilder powinna mieć prywatną składową typu Computer, którą będzie rozbudowywać. Zaimplementuj poniższe metody. Każda z nich powinna zwracać referencję do obiektu buildera, aby umożliwić łączenie wywołań metod:

    • setCPU(const std::string& cpu)
    • setRAM(const std::string& ram)
    • setStorage(const std::string& storage)
    • setGPU(const std::string& gpu)
    • addWifi(): włącza możliwość korzystania z Wi-Fi

    Zaimplementuj również metodę build(), która zwraca gotowy obiekt Computer i resetuje builder, aby można go było ponownie użyć.

  • main.cpp: Połącz wszystkie elementy, aby zbudować niestandardowy komputer.

    Wczytaj cztery dane wejściowe:

    1. Model procesora (string)
    2. Specyfikację pamięci RAM (string)
    3. Specyfikację pamięci masowej (string)
    4. Czy dołączyć Wi-Fi: yes lub no

    Użyj ComputerBuilder, aby zbudować komputer z podanymi procesorem, pamięcią RAM i pamięcią masową. Jeśli wartością wejściową dla Wi-Fi jest yes, wywołaj również addWifi(). Zwróć uwagę, że w tej konfiguracji nie podano karty graficznej: builder powinien poprawnie obsługiwać opcjonalne komponenty.

    Po zbudowaniu komputera wywołaj na nim metodę showSpecs(), aby wyświetlić jego konfigurację.

Metoda showSpecs() powinna wyświetlać dane w następującym formacie (pokazując tylko ustawione komponenty):

CPU: [value]
RAM: [value]
Storage: [value]
GPU: [value]
Wifi: Enabled

Na przykład dla danych wejściowych Intel i7-12700K, 32GB DDR5, 1TB NVMe SSD oraz yes:

CPU: Intel i7-12700K
RAM: 32GB DDR5
Storage: 1TB NVMe SSD
Wifi: Enabled

Dla danych wejściowych AMD Ryzen 5 5600X, 16GB DDR4, 512GB SSD oraz no:

CPU: AMD Ryzen 5 5600X
RAM: 16GB DDR4
Storage: 512GB SSD

Zwróć uwagę, że wzorzec Builder sprawia, iż proces tworzenia obiektu jest czytelny i elastyczny. Możesz z łatwością dodawać lub pomijać komponenty, a łączenie wywołań metod tworzy przejrzysty kod, który sam wyjaśnia swoje działanie. Wiersz dotyczący karty graficznej się nie pojawia, ponieważ jej nie ustawiliśmy. Pokazuje to, jak buildery w naturalny sposób obsługują opcjonalne komponenty.

Spróbuj swoich sił

#include <iostream>
#include <string>
#include "ComputerBuilder.h"

using namespace std;

int main() {
    // Wczytaj dane wejściowe
    string cpu, ram, storage, wifiChoice;
    getline(cin, cpu);
    getline(cin, ram);
    getline(cin, storage);
    getline(cin, wifiChoice);

    // TODO: Utwórz instancję ComputerBuilder
    
    // TODO: Użyj łańcuchowego wywoływania metod, aby ustawić CPU, RAM i pamięć masową
    
    // TODO: Jeśli wifiChoice ma wartość "yes", wywołaj także addWifi()
    
    // TODO: Wywołaj build(), aby uzyskać obiekt Computer
    
    // TODO: Wywołaj showSpecs() na zbudowanym komputerze, aby wyświetlić konfigurację

    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online