🧱
PHPでデザインパターン「Template Method」
目次
概要
Template Methodパターンは親クラスで処理の大きな枠組み(テンプレート)を定義し、具体的な処理内容を子クラスで決定するパターンです。
呼び出し元のクラスからは子クラスの追加や変更が見えないため、処理の変更が容易になります。
実装
<?php
// 親クラス
abstract class AbstractDisplay
{
public function display(): string
{
$html = "";
$html .= $this->displayHeader();
$html .= "<body>";
$html .= $this->displayBody();
$html .= "</body>";
return $html;
}
private function displayHeader(): string
{
return "<head><title>Template Method</title></head>";
}
// 子クラスで具体的な処理を記述
protected abstract function displayBody(): string;
}
<?php
// 子クラス1
class ListDisplay extends AbstractDisplay
{
public function __construct(
private array $data,
) {}
protected function displayBody(): string
{
$body = "";
foreach ($this->data as $key => $value) {
$body .= "<dt>" . $key . "</dt>";
$body .= "<dd>" . $value . "</dd>";
}
return $body;
}
}
// 子クラス2
class TableDisplay extends AbstractDisplay
{
public function __construct(
private array $data,
) {}
protected function displayBody(): string
{
$body = "";
foreach ($this->data as $key => $value) {
$body .= "<tr>";
$body .= "<th>" . $key . "</th>";
$body .= "<td>" . $value . "</td>";
$body .= "</tr>";
}
return $body;
}
}
<?php
use PHPUnit\Framework\TestCase;
// テストコード
class DisplayTest extends TestCase
{
public function test_list_display(): void
{
$data = [
"日本" => "東京",
"アメリカ" => "ワシントン",
"中国" => "北京",
];
$expected = "<html><head><title>Template Method</title></head><body><dt>日本</dt><dd>東京</dd><dt>アメリカ</dt><dd>ワシントン</dd><dt>中国</dt><dd>北京</dd></body></html>";
$ld = new ListDisplay($data);
$result = $ld->display();
$this->assertSame($expected, $result);
}
public function test_table_display(): void
{
$data = [
"日本" => "東京",
"アメリカ" => "ワシントン",
"中国" => "北京",
];
$expected = "<html><head><title>Template Method</title></head><body><tr><th>日本</th><td>東京</td></tr><tr><th>アメリカ</th><td>ワシントン</td></tr><tr><th>中国</th><td>北京</td></tr></body></html>";
$ld = new TableDisplay($data);
$result = $ld->display();
$this->assertSame($expected, $result);
}
}
資料
参考文献『PHPによるデザインパターン入門』https://shimooka.hateblo.jp/entry/20100301/1267436385
Discussion