構造を持ったインスタンスを組み上げていくパターンをBuilderパターンという
「文書」を作成するサンプルプログラムを作る。
ここで作る文章は以下のような構造を持っている。
・タイトルを1つ含む
・文字列をいくつか含む
・箇条書きの項目をいくつか含む
<?php abstract class Builder { public abstract function makeTitle($title); public abstract function makeString($str); public abstract function makeItems($items); public abstract function close(); }
「文書」を作るメソッドたちを宣言している抽象クラス。
<?php require_once("Builder.class.php"); class Director { private $builder; public function __construct($builder) { $builder->makeTitle("Greeting"); $string1 = "朝から昼にかけて"; $builder->makeString($string1); $string_ary1 = array("おはようございます。", "こんにちは。"); $builder->makeItems($string_ary1); $string2 = "夜に"; $builder->makeString($string2); $string_ary2 = array("こんばんは。", "おやすみなさい。", "さようなら。"); $builder->makeItems($string_ary2); $builder->close(); } }
Directorクラスは、Builderクラスで宣言されたメソッドを使って
実際に「文書」を作成するクラス。
<?php require_once('Builder.class.php'); class TextBuilder extends Builder { public function makeTitle($title) { echo "======================================<br />"; echo "『" .$title."』<br />"; echo "<br />"; } public function makeString($str) { echo "■".$str."<br />"; } public function makeItems($items) { for ($i = 0; $i <count($items) ; $i++) { echo " ・".$items[$i]."<br />"; } echo "<br />"; } public function close() { echo "======================================<br />"; } public function getResult() { return ; } }
Builderクラスのサブクラスとして、
プレーンテキストを使って文書を作成する。
<?php require_once("Builder.class.php"); class HTMLBuilder extends Builder { private $filename; private $writer; public function makeTitle($title) { $this->filename = $title."html"; echo "<html><head><title>".$title."</title></head></html>"; echo "<h1>".$title."</h1>"; } public function makeString($str) { echo "<p>".$str."</p>"; } public function makeItems($items) { echo "<ul>"; for ($i = 0; $i < count($items); $i++) { echo "<li>".$items[$i]."</li>"; } echo "</ul>"; } public function close() { echo "</body></html>"; } public function getResult() { return $this->filename; } }
Builderクラスのサブクラスとして、HTMLを使って文書を作成する。
<?php require_once('TextBuilder.class.php'); require_once('Director.class.php'); require_once('HTMLBuilder.class.php'); class Main { public function __construct($type) { if ($type == 'plain') { $textbuilder = new TextBuilder(); $director = new Director($textbuilder); $result = $textbuilder->getResult(); echo $result; } if ($type == 'html') { $htmlbuilder = new HTMLBuilder(); $director = new Director($htmlbuilder); $filename = $htmlbuilder->getResult(); echo $filename; } } } //$type = 'plain'; $type = 'html'; new Main($type);
実行クラス。
TextBuilder?もHTMLBuilderもBuilderクラスのサブクラスであり、
DirectorはBuilderのメソッドのみを使って文書を作る。
つまり、Directorは実際に動いているのがTextBuilder?かHTMLBuilderか
意識していない。
インスタンスを作成するためのインターフェイスを定める。
サンプルプログラムではBuilderクラスがこの役をつとめた。
Builder役のインターフェイスを実装しているクラス。
実際のインスタンス作成で呼び出せるメソッドや、最終的にできた結果を得るためのメソッドを定義する。
サンプルプログラムではTextBuilder?クラスやHTMLBuilderクラスがこの役をつとめた。
Builder役のインターフェイスを使ってインスタンスを生成する。
ConcreteBuilder?役に依存したプログラミングは行わなず、
ConcreteBuilder?役に何があってもいいようにBuilder役のメソッドをのみを使う。
サンプルプログラムではDirectorクラスがこの役をつとめた。
MainクラスはBuilderクラスのメソッドを知らず、Director役のコンンストラクタを使用しているだけ。
Director役はBuilderクラスを知っているが、Builderクラスの実装までは知らない。
このようにクラス同士の関係性が希薄なので、
クラスの入れ替えが可能(=再利用が可能)であり、
これはオブジェクト指向においては大事なことである。
Builderパターンでは、Director役がBuilder役をコントロールする。
一方、Template Methodパターンでは、
スーパークラスがサブクラスをコントロールする。
Builderパターンによって生まれる生成物は、Compositeパターンになる場合がある。
BuildrパターンのDirector役は、Builder役の複雑なメソッドを組み合わせて、
インスタンスを生成するインターフェイスを外部に提供する。
FacadeパターンのFacade役は、内部モジュールを組み合わせて、
作業を行うためのインターフェイスを外部に提供する。
参考資料