PHP でデザインパターン (Template Method)
PHP デザインパターン
Published: 2018-09-29

Template Method パターンとは

スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を定めるようなデザインパターン

クラスの振る舞いに注目したパターンで、サブクラスで具体的な振る舞いを決定させることを目的としています。

Template Method パターンのメリット

  • スーパークラスのテンプレートメソッドでアルゴリズムが記述されており、サブクラス側では アルゴリズムを記述する必要がなくなる

  • 親クラス視点で見ると、「抽象メソッドとして定義したメソッドの実装が「保証される」

  • 子クラス視点で見ると、クライアント側のコードを変更することなく、利用する処理を切り替えることができる。

実装例

<?php
abstract class AbstractDisplay
{
    private $data;

    public function __construct($data)
    {
        if (!is_array($data)) {
            $data = [$data];
        }
        $this->data = $data;
    }

    public function getData()
    {
        return $this->data;
    }

    /**
     * 処理のアルゴリズムがまとまっている
     *
     */
    public function display()
    {
        $this->displayHeader();
        $this->displayBody();
        $this->displayFooter();
    }

    protected abstract function displayHeader();
    protected abstract function displayBody();
    protected abstract function displayFooter();
}

class ListDisplay extends AbstractDisplay
{
    protected function displayHeader()
    {
        echo 'ListDisplay.displayHeader()' . "\n";
    }

    protected function displayBody()
    {
        echo 'ListDisplay.displayBody()' . "\n";
        foreach ($this->getData() as $key => $val) {
            echo $val . "\n";
        }
    }

    protected function displayFooter()
    {
        echo 'ListDisplay.displayFooter()' . "\n";
    }
}

class TableDisplay extends AbstractDisplay
{
    protected function displayHeader()
    {
        echo 'TableDisplay.displayHeader()' . "\n";
    }

    protected function displayBody()
    {
        echo 'TableDisplay.displayBody()' . "\n";
        foreach ($this->getData() as $key => $val) {
            echo sprintf("***%s***\n", $val);
        }
    }

    protected function displayFooter()
    {
        echo 'TableDisplay.displayFooter()' . "\n";
    }
}

$data = [
    'Design Pattern',
    'Gang of Four',
    'Template Method Sample1',
    'Template Method Sample2',
];

$display1 = new ListDisplay($data);
$display2 = new TableDisplay($data);

$display1->display();
echo "------\n";
$display2->display();

おまけ

リスコフの置換原則(LSP:The Liskov Substituion Principle): 「サブクラスの型はその親クラスの型と置換可能」

ハリウッドの原則(The Hollywood Principle:「Don’t call us. We’ll call you.」「我々を呼び出すな。必要なときは、我々が君を呼び出す」

参考