Template Metbodを調べてみた( ・`ω・´)

Template Metbod とは?

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

ポイント

継承と似ているようですが、
「処理の一部分をサブクラスで実装する」
ところがポイントのようです。

メリット

共通な処理をまとめることが出来る

共通の処理を親クラスにまとめることで、
変更があった場合にも親クラスの修正だけで済む

サブクラスにより、具体的な処理内容を変えることが出来る

親クラスの抽象メソッドがサブクラスに実装されますので、
共通ではない処理をサブクラスに書き、
処理内容を変更することが出来ます。
親クラスのメソッドを他のサブクラスと共有して利用出来ますね。

AbstractDisplay.php

AbstractDisplayが親クラスファイルであり
abstractクラスで定義しています。

<?php

abstract class AbstractDisplay
{

    private $data;
    
    public function __construct($data)
    {
        if(!is_array($data))
        {
            $data = array($data);
        }
        $this->data = $data;
    }
    
    public function display()
    {
        $this->displayHeader();
        $this->displayBody();
        $this->displayFooter();
    }
    
    public function getData()
    {
        return $this->data;
    }
    
    protected abstract function displayHeader();
    
    protected abstract function displayBody();
    
    protected abstract function displayFooter();
}
?>
ListDisplay.php
<?php
require_once 'AbstractDisplay.php';

class ListDisplay extends AbstractDisplay
{
    protected function displayHeader()
    {
        echo '<dl>';
    }
    
    protected function displayBody()
    {
        foreach ($this->getData() as $key => $value)
        {
            echo '<dt>Item ' . $key . '</dt>';
            echo '<dd>' . $value . '</dd>';
        }
    }
    
    protected function displayFooter()
    {
        echo '</dl>';
    }
}
?>
TableDisplay.php
<?php
require_once 'AbstractDisplay.php';

class TableDisplay extends AbstractDisplay
{
    protected function displayHeader()
    {
        echo '<table border="1" cellpadding="2" cellspacing="2">';
    }
    
    protected function displayBody()
    {
        foreach ($this->getData() as $key => $value)
        {
            echo '<tr>';
            echo '<th>' . $key . '</th>';
            echo '<td>' . $value . '</td>';
            echo '</tr>';
        }
    }
    
    protected function displayFooter()
    {
        echo '</table>';
    }
}
?>
template_method_client.php
<?php
require_once 'ListDisplay.php';
require_once 'TableDisplay.php';

    $data = array('Design Pattern',
                  'Gang of Four',
                  'Template Method 1',
                  'Template Method 2');

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

    $display1->display();

    echo '<br>';

    $display2->display();
?>

Template Methodパターンは「継承」を利用しているパターンです。
親クラスでは抽象メソッドとして定義されているため、
サブクラスでは必ず実装を行う必要があります。
つまり、抽象化することでメソッドの実装が保証されることになります。

サブクラスは親クラスを継承してるので、
全て親クラスの型とみることが出来るようです。
つまりPHPは自動で型を判定するので事故防止?
または保証されるということですかね?

リスコフの置換原則という原則で定められているようです。
(親クラスとサブクラスを定義するとき、
サブクラスは親クラスを置き換えることが出来なければならない)
置き換えることにより、サブクラスが利用や変更した際にも
親クラスとサブクラスの型は同義となるようです。

また、Template Methodパターンでは
親クラスがサブクラスのメソッドを呼び出す「制御構造の反転」
という特徴を持つパターンのようです。