Builder
Builderは、インスタンス生成の手順をいくつかに分割し、それを別クラスで管理させるパターンです。
例:スープラとロードスターを作る。
ソースはこちら
ちょっと途方もない処理ですが、勘弁してください。スープラもロードスターも、どちらも作り上げるのは 非常に大変ですが、似たようなものです。まず、エンジンやドアなどの部品を作って、 次にそれらの部品を組み立て、最後に安全性などをテストを行います。 しかし、スープラとロードスターでは、使われるエンジンもドアも組み立て方も違いますよね。 全体の流れは似ていても、その1つ1つの具体的な処理は異なります。また、それは非常に複雑なものです。 こういう時はBuilderパターンを適用します。

Builderパターンを適用する時に注意するのは、複雑なインスタンス生成を、単にメソッドに分けるだけでなく、 そのメソッド呼び出しをコントロールするクラスを作成するという点です。実はBuilderパターンは、 Template Methodパターンと似ていますが、 この部分が大きく違います。Template Methodパターンでは、スーパークラスがサブクラスの具体的な 処理手順をコントロールしました。ですが、Builderパターンでは他のクラスがBuilderクラス(インスタンスを 生成するクラス)の処理手順をコントロールします。ここでいう「他のクラス」、 つまり、Builderクラスの処理手順をコントロールするクラスのことをDirectorクラスと呼びます。 なぜ他のクラスにコントロールさせるかというのは、後でお話します。

話を例に戻すと、Builderクラスとしてスープラを作るクラスと、ロードスターを作るクラスが 必要そうですよね。ただし先にも書いたように、どちらも車を作るわけですから、 「車を作る」というクラスを定義してそれを継承させた方が良さそうです。 また、上で説明したように、BuilderパターンにはDeirectorクラスも必要です。

ここまでで必要なクラスを洗い出すと以下のようになります。

CarBuilder 「車を作る」抽象クラス
SupuraBuilder 「スープラを作る」クラス
RoadstarBuilder 「ロードスターを作る」クラス
Director 「車を作る」ことを管理するクラス

では具体的にどういった手順で車を作成するのでしょうか?

ユーザはDirectorクラスに車を作ることを委譲します。Directorクラスは、コンストラクタで与えられた CarBuilderクラスの車を作成します。この時大切なのが、Directorクラスのコンストラクタには、 CarBuilderクラス型の変数を与えるということです。インタフェースプログラミングのポイントは、 インタフェースを与えるべきところにはそのインタフェースを実装したオブジェクトなら 何でも入れられという点です。ですから、Direcotrには、SupuraBuiderでも、RoadstarBuiderでも渡せますし、 後から追加するかも知れないFerrariBuilderやBmwBuilderも、それらがCarBuilderを継承しているなら 渡すことが可能です。

また、何故Directorクラスにインスタンス生成を委譲するのか、という点についてお話します。 今回の例で言うと、Mainクラスで直接、CarBuilderクラスのgetCarメソッドを呼び出してもよさそうです (もちろん、その場合にはabstractではなく、内部を実装しなければなりません)。MainからDirectorへ、 DirectorからCarBuilderへと処理を委譲するのは、MainがCarBuilderの詳細を意識することなく、 CarBuilderを差し替えられるようにするためです。mainメソッド内では、Directorクラスのメソッドしか 使われていません。ユーザはDirecotrクラスだけを気にかければ良く、CarBuilderやそのサブクラスの詳細を 知る必要はないのです。また同時に、それぞれのクラスの責務を分散することが出来ます。 Builderは車を作らなければなりません。車の作る過程は複雑で、その過程まで管理するとなると、 Builderクラスは膨れ上がってしまいます。ですが、Builderパターンを適用すると、Builderクラスは 車を作る1つ1つの処理だけについて定義し、実際に車を作り上げるのはDirectorクラスになります。

実行結果
クラス図