デザインパターン_Builder

## 参照記事
[wiki-Builderパターン](https://ja.wikipedia.org/wiki/Builder_パターン#:~:text=Builder%20パターン（ビルダー・パターン）,生成を可能にする。)
[7. Builder パターン](https://www.techscore.com/tech/DesignPattern/Builder)
[【デザインパターン】ビルダーパターン](https://doriven.hatenablog.com/entry/2014/11/08/040739)

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

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

[7. Builder パターン](https://www.techscore.com/tech/DesignPattern/Builder)より引用

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

[【デザインパターン】ビルダーパターン](https://doriven.hatenablog.com/entry/2014/11/08/040739)より引用

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

[【デザインパターン】ビルダーパターン](https://doriven.hatenablog.com/entry/2014/11/08/040739)より引用

## クラス図
![700px-Builder_UML_class_diagram.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2736795/6e6aed6e-7370-36b1-661f-30c74e33027b.png)
[wiki-Builderパターン](ttps://ja.wikipedia.org/wiki/Builder_パターン#:~:text=Builder%20パターン（ビルダー・パターン）,生成を可能にする。)より引用
## 処理
- Director: `Director`
- Builder: `Builder`
- Building: `Building`
- ConcreteBuilder: `JapaneseHouseBuilder`・`KamakuraBuilder`
[wiki-Builderパターン](ttps://ja.wikipedia.org/wiki/Builder_パターン#:~:text=Builder%20パターン（ビルダー・パターン）,生成を可能にする。)を参考にコーディングしました．
### main
``` C++: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`のメソッドの呼び出しを行う

``` C++: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`で定義しなければいけない関数を制約する

``` C++:Builder.h
template <class T>
concept is_builder = requires(T& obj)
{
    obj.BuildBase();
    obj.BuildFrame();
    obj.BuildWall();
    obj.Print();
};
```

### Building: Building
- `ConcreteBuilder`で設定する素材を定義する

``` C++: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`で制約した関数を定義する
- 素材を設定する

``` C++: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; }
};
```

``` C++: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`
``` output
[Base:CONCRETE, Frame:WOOD, Wall:CLAY]
[Base:SNOW, Frame:SNOW, Wall:SNOW]
```