Menu
Coddy logo textTech

Patron Monteur

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy — leçon 93 sur 104.

Le pattern Builder sépare la construction d'un objet complexe de sa représentation, vous permettant de créer différentes configurations étape par étape. Ceci est particulièrement utile lorsqu'un objet possède de nombreux paramètres optionnels ou nécessite une séquence de construction spécifique.

Au lieu d'un constructeur avec de nombreux paramètres (ce qui devient déroutant), le Builder fournit des méthodes claires et nommées pour chaque option de configuration :

#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();
}

Chaque méthode setter retourne une référence au builder (return *this), permettant le chaînage de méthodes pour une interface fluide. La méthode build() finalise et retourne l'objet construit.

Utilisez Builder lors de la construction d'objets comportant de nombreux composants optionnels, lorsque vous souhaitez un code de construction lisible, ou lorsque le même processus de construction doit créer différentes représentations.

challenge icon

Défi

Facile

Construisons un système Computer Builder qui permet aux utilisateurs de configurer des PC personnalisés étape par étape. C'est un scénario parfait pour le patron de conception Builder (Monteur) — les ordinateurs possèdent de nombreux composants optionnels, et nous voulons une manière propre et lisible d'assembler différentes configurations.

Vous organiserez votre code sur trois fichiers :

  • Computer.h : Définissez la classe du produit qui représente un ordinateur entièrement configuré.

    Votre classe Computer doit stocker ces composants en tant que membres privés : cpu (string), ram (string), storage (string), gpu (string), et hasWifi (boolean). Initialisez hasWifi à false et les chaînes de caractères à vide par défaut.

    Ajoutez une méthode publique appelée showSpecs() qui affiche la configuration de l'ordinateur. Pour chaque composant qui a été défini (chaîne non vide), affichez-le sur sa propre ligne. La capacité wifi ne doit être affichée que si elle est activée.

  • ComputerBuilder.h : Créez la classe builder qui construit des ordinateurs avec une interface fluide.

    Votre classe ComputerBuilder doit avoir un membre privé Computer qu'elle construit. Implémentez ces méthodes, chacune retournant une référence au builder pour permettre le chaînage de méthodes :

    • setCPU(const std::string& cpu)
    • setRAM(const std::string& ram)
    • setStorage(const std::string& storage)
    • setGPU(const std::string& gpu)
    • addWifi() — active la capacité wifi

    Implémentez également une méthode build() qui retourne l'objet Computer terminé et réinitialise le builder pour une éventuelle réutilisation.

  • main.cpp : Rassemblez le tout pour construire un ordinateur personnalisé.

    Lisez quatre entrées :

    1. Modèle de CPU (string)
    2. Spécification de la RAM (string)
    3. Spécification du stockage (string)
    4. S'il faut inclure le wifi : yes ou no

    Utilisez le ComputerBuilder pour construire un ordinateur avec le CPU, la RAM et le stockage fournis. Si l'entrée wifi est yes, appelez également addWifi(). Notez qu'aucun GPU n'est spécifié dans cette configuration — le builder doit gérer les composants optionnels avec élégance.

    Après la construction, appelez showSpecs() sur l'ordinateur résultant pour afficher sa configuration.

La méthode showSpecs() doit produire une sortie dans ce format (en affichant uniquement les composants qui ont été définis) :

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

Par exemple, avec les entrées Intel i7-12700K, 32GB DDR5, 1TB NVMe SSD, et yes :

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

Avec les entrées AMD Ryzen 5 5600X, 16GB DDR4, 512GB SSD, et no :

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

Remarquez comment le patron Builder rend le processus de construction lisible et flexible — vous pouvez facilement ajouter ou ignorer des composants, et le chaînage de méthodes crée un code clair et auto-documenté. La ligne GPU n'apparaît pas car nous ne l'avons jamais définie, démontrant comment les builders gèrent naturellement les composants optionnels.

Aide-mémoire

Le pattern Builder (ou patron de conception Monteur) sépare la construction d'un objet complexe de sa représentation, permettant une configuration étape par étape. Il est utile lorsqu'un objet possède de nombreux paramètres optionnels ou nécessite une séquence de construction spécifique.

Au lieu de constructeurs avec de nombreux paramètres, le Builder fournit des méthodes nommées claires pour chaque option de configuration :

class Pizza {
public:
    std::string dough;
    std::string sauce;
    std::string topping;
    bool cheese;
};

class PizzaBuilder {
private:
    Pizza pizza;
    
public:
    PizzaBuilder& setDough(const std::string& d) {
        pizza.dough = d;
        return *this;  // Enable method chaining
    }
    
    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; }
};

// Usage with method chaining
Pizza margherita = PizzaBuilder()
    .setDough("thin")
    .setSauce("tomato")
    .setTopping("basil")
    .addCheese()
    .build();

Chaque méthode "setter" renvoie return *this pour permettre le chaînage de méthodes pour une interface fluide. La méthode build() finalise et renvoie l'objet construit.

Utilisez le Builder lors de la construction d'objets comportant de nombreux composants optionnels, lorsque vous souhaitez un code de construction lisible, ou lorsque le même processus de construction doit créer différentes représentations.

Essayez vous-même

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

using namespace std;

int main() {
    // Lire les entrées
    string cpu, ram, storage, wifiChoice;
    getline(cin, cpu);
    getline(cin, ram);
    getline(cin, storage);
    getline(cin, wifiChoice);

    // TODO: Créer une instance de ComputerBuilder
    
    // TODO: Utiliser le chaînage de méthodes pour définir le CPU, la RAM et le storage
    
    // TODO: Si wifiChoice est "yes", appeler également addWifi()
    
    // TODO: Appeler build() pour obtenir l'objet Computer
    
    // TODO: Appeler showSpecs() sur l'ordinateur construit pour afficher la configuration

    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet