絶版されているけれど、Google booksで公開されているのが見れます。
https://books.google.co.jp/books?id=sXNh4TeQeBIC&printsec=frontcover&hl=ja#v=onepage&q&f=false
1日1パターンってことで演習してアウトプットしていきます。
もくじ
使いどころ
- 似たような処理がたくさんできることがある時
- 処理フローがほとんど同じだが、ごく一部が異なる時
似た処理やまったく同じ処理だからと、コピペでクラスを作るとその処理にバグがあった時にすべてのクラスを修正することになる。
実装のポイント
- 異なる処理の部分だけを分けておいて、クラス毎にその処理を実装すれば良いようにしておく。
- 親クラスでは、具体的に処理内容が変わる部分をわざと抽象メソッドにしている。
これによって抽象メソッドを実装しないと親クラスが提供している機能を使えない。
→ 親クラスの視点から見ると、抽象メソッドとして定義したメソッドの実装が「保証される」
Template Methodのメリット
- それぞれのサブクラスの共通処理を親クラスにまとめることが出来る
サブクラス側に共通処理部分を記述する必要がなくなる - 共通部分の似た処理でバグや変更があっても、抽象クラスだけを修正すれば良くなる
AbstractDisplay.class.php
<?php /** * AbstractClassクラスに相当する */ abstract class AbstractDisplay { /** * 表示するデータ */ private $data; /** * コンストラクタ * @param mixed 表示するデータ */ public function __construct($data) { if(!is_array($data)) { $data = array($data); } $this->data = $data; } /** * template methodに相当する */ 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(); }
TableDisplay.class.php
<?php require_once 'AbstractDisplay.class.php'; /** * ConcreteClassクラスに相当する */ 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>Item ' . $key . '</th>'; echo '<td>Item ' . $value . '</td>'; echo '</tr>'; } } /** * フッタを表示する */ protected function displayFooter() { echo '</table>'; } }
ListDisplay.class.php
<?php require_once 'AbstractDisplay.class.php'; /** * ConcreteClassクラスに相当する */ 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>Item ' . $value . '</dd>'; } } /** * フッタを表示する */ protected function displayFooter() { echo '</dl>'; } }
index.php
<?php require_once 'ListDisplay.class.php'; require_once 'TableDisplay.class.php'; $data = array( 'Desing Pattern', 'Gang of Four', 'Template Method Sample1', 'Template Method Sample2', ); $display1 = new ListDisplay($data); $display2 = new TableDisplay($data); $display1->display(); echo '<hr/>'; $display2->display();
表示結果
@see