ビルダーモード
ビルダーモードは、複数のコンポーネントを含む複雑なオブジェクトの作成からクライアントを分離します。クライアントは、複雑なオブジェクトの内部構成とメソッドを知る必要はありませんが、必要なビルダーを知る必要があるだけです。
言い換えれば、開発者は家を建てるときに、建てたい家の設計図を建設者に渡し、建設者は設計された建設プロセスに従って基礎を築き、家を建て、室内装飾を行います。開発者のみ資格のある建設業者に連絡し、残りは建設業者に任せて建設するだけです。建設業者は、開発者の設計図に従ってさまざまなスタイルの家を建てます。
ビルダーパターンの定義:同じ構築プロセスで異なる表現を作成できるように、複雑なオブジェクトの構築をその表現から分離します。
ビルダーモードの構造
ビルダーモードの構造には、次の役割が含まれます。
- Abstract Builder(AbstractBuilder):Productオブジェクトの各コンポーネントで指定された抽象インターフェースを作成します。
- Concrete Builder(ConcreteBuilder):AbstractBuilderインターフェースを実装し、各コンポーネントの具体的な構築メソッドとアセンブリメソッドを実装し、作成結果を返します。
- 製品:特定の製品オブジェクト
- Director:Builderインターフェースを使用してオブジェクトを作成し、複雑なオブジェクトの作成を調整します。クライアントは通常、Directorと対話し、Builderタイプを指定してから、コンストラクターまたはセッターメソッドを介して具体的なBuilderオブジェクトをDirectorに渡すだけです。その主な機能は、顧客とオブジェクトの製造プロセスを分離し、製品オブジェクトの製造プロセスを制御することです。
UML図:UML図を
見てください。ディレクターは必要に応じて適切なビルダーを選択し、ビルダーは対応する製品をビルドします。Directorは、BuilderがProductの生産プロセスをどのように実装するかを知る必要はありません。
ビルダーモードのコード例
BuilderPattern.h
#include <iostream>
#include <string.h>
using namespace std;
//产品类House
class House
{
public:
House() {
}
void setFloor(string iFloor)
{
this->floor = iFloor;
}
void setWall(string iWall)
{
this->wall = iWall;
}
void setRoof(string iRoof)
{
this->roof = iRoof;
}
//打印House信息
void printfHouseInfo()
{
cout << "Floor " << this->floor.c_str() << "\n";
cout << "Wall " << this->wall.c_str() << "\n";
cout << "Roof " << this->roof.c_str() << "\n\n";
}
private:
string floor;
string wall;
string roof;
};
//抽象建造者AbstractBuilder
class AbstractBuilder
{
public:
AbstractBuilder()
{
house = new House();
}
virtual ~AbstractBuilder()
{
if (house != nullptr)
{
house = nullptr;
delete house;
}
}
//抽象方法:
virtual void buildFloor() = 0;
virtual void buildWall() = 0;
virtual void buildRoof() = 0;
virtual House *getHouse() = 0;
House *house;
};
//具体建造者ConcreteBuilderA
class ConcreteBuilderA : public AbstractBuilder
{
public:
ConcreteBuilderA()
{
printf("ConcreteBuilderA\n");
}
~ConcreteBuilderA()
{
if (this->house != nullptr)
{
house = nullptr;
delete house;
}
}
//具体实现方法
void buildFloor()
{
this->house->setFloor("Floor_A");
}
void buildWall()
{
this->house->setWall("Wall_A");
}
void buildRoof()
{
this->house->setRoof("Roof_A");
}
House *getHouse()
{
return this->house;
}
};
//具体建造者ConcreteBuilderB
class ConcreteBuilderB : public AbstractBuilder
{
public:
ConcreteBuilderB()
{
printf("ConcreteBuilderB\n");
}
~ConcreteBuilderB()
{
if (this->house != nullptr)
{
house = nullptr;
delete house;
}
}
//具体实现方法
void buildFloor()
{
this->house->setFloor("Floor_B");
}
void buildWall()
{
this->house->setWall("Wall_B");
}
void buildRoof()
{
this->house->setRoof("Roof_B");
}
House *getHouse()
{
return this->house;
}
};
//指挥者Director
class Director
{
public:
Director() : builder(nullptr) {
}
~Director()
{
if (this->builder != nullptr)
{
builder = nullptr;
delete builder;
}
}
//具体实现方法
void setBuilder(AbstractBuilder *iBuilder)
{
this->builder = iBuilder;
}
House *construct()
{
builder->buildFloor();
builder->buildWall();
builder->buildRoof();
return builder->getHouse();
}
private:
AbstractBuilder *builder;
};
BuilderPattern.cpp
#include "BuilderPattern.h"
int main()
{
// 抽象建造者 builder
AbstractBuilder *builder;
// 装饰者
Director *director = new Director();
// 产品类:house
House *house;
// 新建具体建造者A
builder = new ConcreteBuilderA();
director->setBuilder(builder);
house = director->construct();
house->printfHouseInfo();
delete builder;
// 新建具体建造者B
builder = new ConcreteBuilderB();
director->setBuilder(builder);
house = director->construct();
house->printfHouseInfo();
director->~Director();
builder->~AbstractBuilder();
return 0;
}
ビルダーモードの概要
クライアントからは、顧客が必要に応じて対応するビルダーを指定し、そのビルダーをパラメーターとしてコマンダーに渡し、コマンダーを介して結果を取得できることがわかります。クライアントは、製品の特定の構築プロセスを気にする必要はありません。
工法を変更したい場合は、特定のビルダーを変更するだけで、異なるビルダー間の接続がないため、交換に便利です。実際、コードの最適化の観点からは、ディレクターの役割は不要であり、constructメソッドを具体的なビルダーに直接組み込むことができます。
利点:
- ビルダーモードでは、クライアントは製品の内部構成の詳細を知る必要がなく、製品自体を製品作成プロセスから分離するため、同じ作成プロセスで異なる製品オブジェクトを作成できます。
- 異なるビルダーは互いに独立しており、交換に便利なチェーンがありません。
短所:
- ビルダーモードで作成された製品は、一般的に共通点が多く、コンポーネントも類似しています。製品間の違いが大きい場合、ビルダーモードは使用に適さないため、使用範囲には一定の制限があります。
- 製品の内部変更が複雑な場合、この変更を実現するために多くの特定のビルダークラスを定義する必要が生じ、システムが非常に大きくなる可能性があります。
該当する環境:
- 生成する必要のある製品オブジェクトは、複雑な内部構造を持っています(通常は複数のメンバー変数を含みます)。
- 製品オブジェクトの内部属性には、特定の生成シーケンスがあります。
- 同じ作成プロセスが多くの異なる製品に適用されます。