LoginSignup
1
2

More than 1 year has passed since last update.

デザインパターン_Builder

Last updated at Posted at 2022-11-02

参照記事

wiki-Builderパターン
7. Builder パターン
【デザインパターン】ビルダーパターン

Builderパターンとは

Builderパターンとは,生成に関するデザインパターンである.
複雑な処理や,値が少しだけ違う処理を多く作る場合に使われます.

例:

例えば、家を建てることを考えてみます。完成する家がどのような家になるかというのは「家の構築過程」と「素材」大きく2つの要素で
決定されると考えてみてください。「作成過程」とは、「どのような順番で、どこに何を配置していくか」というようなことであり、
「素材」とは、「柱には何を使って、壁には何を使って・・・」ということであると考えてください。
このとき、「作成過程」には、"平屋を建てるための作成過程" や "2階建ての家を建てるための作成過程"、
または "少し変わった平屋を建てるための作成過程" など様々なものが考えられます。
同様に、「素材」にも、"柱は木で、壁は土壁、屋根は瓦" などのような和風の家を建てるための素材を用いることもあれば、
"柱は鉄で壁と屋根はコンクリート" といった場合も考えられます。
これらをそれぞれ用意しておくことで、『 "ちょっと変わった平屋を建てる作成過程" で "柱は鉄で壁と屋根はコンクリート" の家を建ててください』という要望に柔軟に応えることができるようになります。
Builder パターンとは、このような、「作成過程」を決定する Director と呼ばれるものと「表現形式」を決定する Builder と呼ばれるものを組み合わせることで、オブジェクトの生成をより柔軟にし、
そのオブジェクトの「作成過程」をもコントロールすることができるようにするためのパターンです。

7. Builder パターンより引用

メリット

・複雑なオブジェクトの構築方法をカプセルできる
・複数の変化するプロセスで、オブジェクトを構築できます(オプション機能)
・製品の内部表現をカプセル化することもできる
・クライアントには中小インタフェースしか見えないため、交換が容易になる

【デザインパターン】ビルダーパターンより引用

デメリット

・シンプルな構造のインスタンス生成に適応しても、意味がなく工数が増えてしまう
・どのような情報を渡す必要性があるのか、ということをクライアント側が知っていなくてはならない

【デザインパターン】ビルダーパターンより引用

クラス図

700px-Builder_UML_class_diagram.svg.png
wiki-Builderパターンより引用

処理

  • Director: Director
  • Builder: Builder
  • Building: Building
  • ConcreteBuilder: JapaneseHouseBuilderKamakuraBuilder
    wiki-Builderパターンを参考にコーディングしました.

main

main.cpp
#include <iostream>
#include "Director.h"
#include "JapaneseHouseBuilder.h"
#include "KamakuraBuilder.h"

int main()
{
    Director<JapaneseHouseBuilder> d1;
    Director<KamakuraBuilder> d2;

    d1.construct();
    d2.construct();
    return 0;
}

Director: Director

  • ConcreteBuilderのメソッドの呼び出しを行う
Director.h
#include "Builder.h"

template <is_builder builder>
class Director
{
private:
    builder obj;
public:
    void construct()
    {
        obj.BuildBase();
        obj.BuildFrame();
        obj.BuildWall();
        obj.Print();
    }
};

Builder: Builder

  • conceptを使用してBuildingで定義しなければいけない関数を制約する
Builder.h
template <class T>
concept is_builder = requires(T& obj)
{
    obj.BuildBase();
    obj.BuildFrame();
    obj.BuildWall();
    obj.Print();
};

Building: Building

  • ConcreteBuilderで設定する素材を定義する
Building.h
#include <string>

using namespace std;

class Building
{
private:
    string Base;
    string Frame;
    string Wall;
public:

    void SetBase(const string base) { this->Base = base; }
    void SetFrame(const string frame) { this->Frame = frame; }
    void SetWall(const string wall) { this->Wall = wall; }

    string GetMaterial() {
        return
            "[Base:" + Base + ", "
            + "Frame:" + Frame + ", "
            + "Wall:" + Wall
            +"]";
    }
};

ConcreteBuilder: JapaneseHouseBuilder・KamakuraBuilder

  • Builderで制約した関数を定義する
  • 素材を設定する
JapaneseHouseBuilder.h
#include "Building.h"
#include <iostream>

using namespace std;
class JapaneseHouseBuilder {
private:
    Building builder;
public:
    JapaneseHouseBuilder() {}
    ~JapaneseHouseBuilder() {}

    void BuildBase() { builder.SetBase("CONCRETE"); }

    void BuildFrame() { builder.SetFrame("WOOD"); }

    void BuildWall() { builder.SetWall("CLAY"); }

    void Print() { cout << builder.GetMaterial() << endl; }
};
KamakuraBuilder.h
#include "Building.h"
#include <iostream>

class KamakuraBuilder {
private:
    Building builder;
public:
    KamakuraBuilder() {}
    ~KamakuraBuilder() {}

    void BuildBase() { builder.SetBase("SNOW"); }

    void BuildFrame() { builder.SetFrame("SNOW"); }

    void BuildWall() { builder.SetWall("SNOW"); }

    void Print() { cout << builder.GetMaterial() << endl; }
};

出力

上がJapaneseHouseBuilder
下がKamakuraBuilder

[Base:CONCRETE, Frame:WOOD, Wall:CLAY]
[Base:SNOW, Frame:SNOW, Wall:SNOW]
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2