Menu
Coddy logo textTech

Builderパターン

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 93/104。

Builderパターンは、複雑なオブジェクトの構築とその表現を分離し、さまざまな構成を段階的に作成できるようにします。これは、オブジェクトに多くのオプションパラメーターがある場合や、特定の構築手順が必要な場合に特に便利です。

多くのパラメーターを持つコンストラクター(わかりにくくなってしまいます)の代わりに、Builder は各構成オプションに対して、明確で名前付きのメソッドを提供します。

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

各セッターメソッドは builder への参照(return *this)を返し、流暢なインターフェースでのメソッドチェーンを可能にします。build() メソッドは構築されたオブジェクトを完成させて返します。

多くのオプションコンポーネントを持つオブジェクトを構築する場合、読みやすい構築コードにしたい場合、または同じ構築プロセスで異なる表現を作成する場合は、Builderを使用します。

challenge icon

チャレンジ

簡単

ユーザーがカスタムPCを手順に沿って構成できるComputer Builderシステムを作りましょう。これはBuilderパターンに最適なシナリオです。computerには多くのオプションのcomponentsがあり、さまざまなconfigurationをすっきりと読みやすい方法で組み立てたいからです。

コードを3つのファイルに整理します。

  • Computer.h: 完全に構成されたcomputerを表すproduct classをdefineします。

    Computer classには、次のcomponentsをprivateメンバーとして保存します。cpu(string)、ram(string)、storage(string)、gpu(string)、hasWifi(boolean)です。hasWififalseに、stringはデフォルトでemptyに初期化します。

    computerのconfigurationを表示するshowSpecs()というpublic methodを追加します。設定されている各component(emptyでないstring)を、それぞれ1行に表示します。wifi機能はEnabledの場合にのみ表示します。

  • ComputerBuilder.h: fluent interfaceでcomputerを構築するbuilder classをCreateします。

    ComputerBuilder classには、構築対象のprivate Computerメンバーを持たせます。次のmethodsをImplementし、それぞれbuilderへのreferenceを返してmethod chainingをEnableします。

    • setCPU(const std::string& cpu)
    • setRAM(const std::string& ram)
    • setStorage(const std::string& storage)
    • setGPU(const std::string& gpu)
    • addWifi(): wifi機能をenablesします

    さらに、完成したComputer objectを返し、再利用に備えてbuilderをresetするbuild() methodもImplementします。

  • main.cpp: すべてをまとめてカスタムcomputerをbuildします。

    4つのinputsを読み取ります。

    1. CPU model(string)
    2. RAM specification(string)
    3. Storage specification(string)
    4. wifiをincludeするかどうか: yesまたはno

    提供されたCPU、RAM、storageを使ってcomputerを構築するためにComputerBuilderを使用します。wifiのinputがyesの場合は、addWifi()もcallします。このconfigurationではGPUを指定していないことに注意してください。builderはオプションのcomponentsを適切に処理する必要があります。

    buildした後、完成したcomputerでshowSpecs()をcallして、そのconfigurationを表示します。

showSpecs() methodは、次の形式でoutputする必要があります(設定されたcomponentsのみを表示します)。

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

たとえば、inputsがIntel i7-12700K32GB DDR51TB NVMe SSDyesの場合:

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

inputsがAMD Ryzen 5 5600X16GB DDR4512GB SSDnoの場合:

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

Builderパターンによって、construction processが読みやすく柔軟になることに注目してください。componentsを簡単に追加またはskipでき、method chainingによって明確でself-documentingなcodeになります。GPUの行が表示されないのは、GPUを一度も設定していないためです。これは、buildersがoptional componentsを自然に処理することを示しています。

自分で試してみよう

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

using namespace std;

int main() {
    // 入力を読み取る
    string cpu, ram, storage, wifiChoice;
    getline(cin, cpu);
    getline(cin, ram);
    getline(cin, storage);
    getline(cin, wifiChoice);

    // TODO: ComputerBuilder のインスタンスを作成する
    
    // TODO: メソッドチェーンを使って CPU、RAM、storage を設定する
    
    // TODO: wifiChoice が "yes" の場合、addWifi() も呼び出す
    
    // TODO: build() を呼び出して Computer オブジェクトを取得する
    
    // TODO: 構築したコンピュータで showSpecs() を呼び出して構成を表示する

    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C++オンラインコンパイラ