参照記事
wiki-Builderパターン
7. Builder パターン
【デザインパターン】ビルダーパターン
Builderパターンとは
Builderパターンとは,生成に関するデザインパターンである.
複雑な処理や,値が少しだけ違う処理を多く作る場合
に使われます.
例:
例えば、家を建てることを考えてみます。完成する家がどのような家になるかというのは「家の構築過程」と「素材」大きく2つの要素で
決定されると考えてみてください。「作成過程」とは、「どのような順番で、どこに何を配置していくか」というようなことであり、
「素材」とは、「柱には何を使って、壁には何を使って・・・」ということであると考えてください。
このとき、「作成過程」には、"平屋を建てるための作成過程" や "2階建ての家を建てるための作成過程"、
または "少し変わった平屋を建てるための作成過程" など様々なものが考えられます。
同様に、「素材」にも、"柱は木で、壁は土壁、屋根は瓦" などのような和風の家を建てるための素材を用いることもあれば、
"柱は鉄で壁と屋根はコンクリート" といった場合も考えられます。
これらをそれぞれ用意しておくことで、『 "ちょっと変わった平屋を建てる作成過程" で "柱は鉄で壁と屋根はコンクリート" の家を建ててください』という要望に柔軟に応えることができるようになります。
Builder パターンとは、このような、「作成過程」を決定する Director と呼ばれるものと「表現形式」を決定する Builder と呼ばれるものを組み合わせることで、オブジェクトの生成をより柔軟にし、
そのオブジェクトの「作成過程」をもコントロールすることができるようにするためのパターンです。
7. Builder パターンより引用
メリット
・複雑なオブジェクトの構築方法をカプセルできる
・複数の変化するプロセスで、オブジェクトを構築できます(オプション機能)
・製品の内部表現をカプセル化することもできる
・クライアントには中小インタフェースしか見えないため、交換が容易になる
デメリット
・シンプルな構造のインスタンス生成に適応しても、意味がなく工数が増えてしまう
・どのような情報を渡す必要性があるのか、ということをクライアント側が知っていなくてはならない
クラス図
wiki-Builderパターンより引用
処理
- Director:
Director
- Builder:
Builder
- Building:
Building
- ConcreteBuilder:
JapaneseHouseBuilder
・KamakuraBuilder
wiki-Builderパターンを参考にコーディングしました.
main
#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
のメソッドの呼び出しを行う
#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
で定義しなければいけない関数を制約する
template <class T>
concept is_builder = requires(T& obj)
{
obj.BuildBase();
obj.BuildFrame();
obj.BuildWall();
obj.Print();
};
Building: Building
-
ConcreteBuilder
で設定する素材を定義する
#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
で制約した関数を定義する - 素材を設定する
#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; }
};
#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]