第8章


Builderパターン(複雑なインスタンスを組み立てる)

「Builder」とは?

構造を持ったインスタンスを組み上げていくパターンをBuilderパターンという

Builderの具体例 (サンプルプログラム)

「文書」を作成するサンプルプログラムを作る。
ここで作る文章は以下のような構造を持っている。

 ・タイトルを1つ含む
 ・文字列をいくつか含む
 ・箇条書きの項目をいくつか含む

Builderクラス

<?php

abstract class Builder {

    public abstract function makeTitle($title);
    public abstract function makeString($str);
    public abstract function makeItems($items);
    public abstract function close();

}

「文書」を作るメソッドたちを宣言している抽象クラス。

Directorクラス

<?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クラスで宣言されたメソッドを使って
実際に「文書」を作成するクラス。


TxetBuilder?クラス

<?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クラスのサブクラスとして、
プレーンテキストを使って文書を作成する。

HTMLBuilderクラス

<?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を使って文書を作成する。

Mainクラス

<?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(建設者)

インスタンスを作成するためのインターフェイスを定める。
サンプルプログラムではBuilderクラスがこの役をつとめた。


ConcreteBuilder?(具体的建設者)

Builder役のインターフェイスを実装しているクラス。
実際のインスタンス作成で呼び出せるメソッドや、最終的にできた結果を得るためのメソッドを定義する。
サンプルプログラムではTextBuilder?クラスやHTMLBuilderクラスがこの役をつとめた。

Director(監督者)

Builder役のインターフェイスを使ってインスタンスを生成する。
ConcreteBuilder?役に依存したプログラミングは行わなず、
ConcreteBuilder?役に何があってもいいようにBuilder役のメソッドをのみを使う。
サンプルプログラムではDirectorクラスがこの役をつとめた。

Builderパターンの利点

誰が何を知っているか

MainクラスはBuilderクラスのメソッドを知らず、Director役のコンンストラクタを使用しているだけ。
Director役はBuilderクラスを知っているが、Builderクラスの実装までは知らない。

このようにクラス同士の関係性が希薄なので、
クラスの入れ替えが可能(=再利用が可能)であり、
これはオブジェクト指向においては大事なことである。

関連しているパターン


Template Methodパターン

Builderパターンでは、Director役がBuilder役をコントロールする。
一方、Template Methodパターンでは、
スーパークラスがサブクラスをコントロールする。

Compositeパターン

Builderパターンによって生まれる生成物は、Compositeパターンになる場合がある。

Facadeパターン

BuildrパターンのDirector役は、Builder役の複雑なメソッドを組み合わせて、
インスタンスを生成するインターフェイスを外部に提供する。
FacadeパターンのFacade役は、内部モジュールを組み合わせて、
作業を行うためのインターフェイスを外部に提供する。


参考資料

  • Java言語で学ぶデザインパターン入門