ビルダーパターン

このパターンはよくあるカプセル化に感じる... シンプルファクトリよりどこが優れているのか分からない

ビルダーパターン

モチベーション

  • 複雑なオブジェクトの生成プロセスとその表現を分離し、同一の生成プロセスで異なる表現を持つオブジェクトを生成できるようにする
  • 多くの部分や設定オプションを含む複雑なオブジェクトを生成する必要があり、かつ生成プロセスを表現から分離したい場合に有効
  • 異なる構成のオブジェクトを柔軟に構築しつつ、生成プロセスの明快さと保守性を維持するのを助ける

クラシックなBuilderパターン

コンピュータ(PC)を構築するプロセスを例に考えてみましょう。異なるパラメータを持つPCを構築する必要があるとします。この場合、異なるPCBuilderクラスを実装することで対応できます。これらのビルダークラスは、いくつかのテンプレートメソッドを定義した共通の基底クラスを継承します。

// PC.h
#pragma once
#include <string>
#include <iostream>
#include <memory>

class PC
{
public:
    void setCPU(const std::string& cpu)
    {
        this->cpu = cpu;
    }
    void setMemory(const std::string& memory)
    {
        this->memory = memory;
    }
    void setStorage(const std::string& storage)
    {
        this->storage = storage;
    }

    void display() const
    { 
        std::cout << "CPU: " << cpu << std::endl;
        std::cout << "Memory: " << memory << std::endl;
        std::cout << "Storage: " << storage << std::endl;
    }

private:
    std::string cpu;
    std::string memory;
    std::string storage;
};

// PCBuilder.h
#pragma once
#include "PC.h"

class PCBuilder
{
public:
    virtual ~PCBuilder() = default;
    virtual void buildCPU() = 0;
    virtual void buildMemory() = 0;
    virtual void buildStorage() = 0;
    virtual PC assemble() = 0;
};

// GamingPCBuilder.h
#pragma once
#include "PCBuilder.h"

class GamingPCBuilder : public PCBuilder
{
public:
    GamingPCBuilder()
    {
        pc = std::make_unique<PC>();
    }

    void buildCPU() override
    {
        pc->setCPU("Intel Core i9-13900K");
    }

    void buildMemory() override
    {
        pc->setMemory("32GB DDR5 6000MHz");
    }

    void buildStorage() override
    {
        pc->setStorage("2TB NVMe SSD");
    }

    PC assemble() override
    {
        return *pc;
    }

private:
    std::unique_ptr<PC> pc;
};

// CustomPCBuilder.h
#pragma once
#include "PC.h"

class CustomPCBuilder
{
public:
    CustomPCBuilder()
    {
        pc = std::make_unique<PC>();
    }

    CustomPCBuilder& withCPU(const std::string& cpu)
    {
        pc->setCPU(cpu);
        return *this;
    }

    CustomPCBuilder& withMemory(const std::string& memory)
    {
        pc->setMemory(memory);
        return *this;
    }

    CustomPCBuilder& withStorage(const std::string& storage)
    {
        pc->setStorage(storage);
        return *this;
    }

    PC construct()
    {
        return *pc;
    }

private:
    std::unique_ptr<PC> pc;
};

ファクトリーパターンとビルダーパターンの違い

ファクトリーパターンは、複数のクラスの機能的なコンポーネント全体のロジックの実装に焦点を当てる
ビルダーパターンは、一つのオブジェクト内部の具体的な詳細の実装に焦点を当てる(例:PC内の具体的な構成)

タグ: C++ デザインパターン ビルダーパターン オブジェクト指向

6月26日 23:01 投稿