TemplateMethodパターンをPHPで書いてみた
TemplateMethodパターンとは?
このパターンの役割は、重複した実装の洗練・整理です。
流れは一緒だけれども、内部の処理が違う処理においてそれぞれの処理を分けることが出来ます。
なので、使い所としては、複数種類のフォーマットで出力をするとき(.txt, .html, .csvなど)などに使えます。
- AbstractClass : 処理の枠組みを定義するクラス。このクラスの中に、枠組みを決めるTemplateMethodが存在しています。
- ConcreteMethod : AbstractClassを継承するサブクラス。Abstractで定義された抽象メソッドの中身を実装しています。
今回は、こちらの本のに書かれているコードを参考に作成しました。
こちらはJavaで書かれていますので、それをPHPに書き直してみました。
TemplateMethodパターン適用前
今回は、例としてコーヒーと紅茶を淹れるプログラムを作ります。
テンプレートメソッドパターンを適用させる前に、一度そのままコードを書いてみましょう。
<?php
class Coffee {
public function describeBeverage() {
echo "--------------------------------\n";
echo 'コーヒーを作ります。\n';
}
public function boilWater() {
echo'お湯を沸かします。\n';
}
public function brew() {
echo 'コーヒー豆を挽き、ドリップします。\n';
}
public function pourInCup() {
echo 'カップに注ぎます。\n';
}
public function addContents() {
echo '砂糖とミルクを足します。\n';
}
public function makeBeverage() {
$this->describeBeverage();
$this->boilWater();
$this->brew();
$this->pourInCup();
$this->addContents();
}
}
<?php
class Tea {
public function describeBeverage() {
echo "--------------------------------\n";
echo "紅茶を作ります。\n";
}
public function boilWater() {
echo "お湯を沸かします。\n";
}
public function brew() {
echo "ティーバッグを浸します。\n";
}
public function pourInCup() {
echo "カップに注ぎます。\n";
}
public function addContents() {
echo "レモンを足します。\n";
}
public function makeBeverage() {
$this->describeBeverage();
$this->boilWater();
$this->brew();
$this->pourInCup();
$this->addContents();
}
}
<?php
require_once 'Coffee.php';
require_once 'Tea.php';
$coffee = new Coffee();
$tea = new Tea();
$coffee->makeBeverage();
$tea->makeBeverage();
--------------------------------
【コーヒーを作ります】
お湯を沸かします
コーヒー豆を挽き、ドリップします
カップに注ぎます
砂糖とミルクを足します
--------------------------------
【紅茶を作ります】
お湯を沸かします
ティーパックを浸します
カップに注ぎます
レモンを足します
出来ましたか?確かに動いていますね!では、なぜテンプレートメソッドを使う必要があるのでしょうか?
CoffeeクラスとTeaクラス、よく見ると同じ処理をそれぞれで書いていますね。
少なくともboilWater()
とpourInCup()
は全く同じことをやっています。
他に飲み物が増えた時、全てのクラスに同じ処理を書くのはしんどいですよね…そこで、これらの共通する処理を枠組みとして定義するのがテンプレートメソッドパターンです!!!!!
まず、共通する処理を定義する抽象クラスを作成しましょう。
ここでは、各クラスの共通処理をメソッドとして定義し、クラスによって異なる処理を抽象メソッドとして定義します。
これを行うことによって、サブクラスはクラス独自の処理(今回の場合だと、brew()
とaddContents()
)だけを記述するだけで良くなります。
TemplateMethodパターン適用後
<?php
abstract class CaffeineBeverage {
/**
* 各クラスの共通の処理
*/
public function describeBeverage($beverage_name) {
echo "--------------------------------\n";
echo "【" . $beverage_name . "を作ります】\n";
}
public function boilWater() {
echo "お湯を沸かします\n";
}
public function pourInCup() {
echo "カップに注ぎます\n";
}
/**
* 各クラスによって異なる処理。抽象クラスとして定義
* 中身はサブクラスで実装してもらう
*/
abstract protected function brew();
abstract protected function addContents();
/**
* TemplateMethod
*/
public function makeBeverage($beverage_name) {
//一連の動作を定義
$this->describeBeverage($beverage_name);
$this->boilWater();
$this->brew();
$this->pourInCup();
$this->addContents();
}
}
<?php
abstract class CaffeineBeverage {
/**
* 各クラスの共通の処理
*/
public function describeBeverage($beverage_name) {
echo "--------------------------------\n";
echo "【" . $beverage_name . "を作ります】\n";
}
public function boilWater() {
echo "お湯を沸かします\n";
}
public function pourInCup() {
echo "カップに注ぎます\n";
}
/**
* 各クラスによって異なる処理。抽象クラスとして定義
* 中身はサブクラスで実装してもらう
*/
abstract protected function brew();
abstract protected function addContents();
/**
* TemplateMethod
*/
public function makeBeverage($beverage_name) {
//一連の動作を定義
$this->describeBeverage($beverage_name);
$this->boilWater();
$this->brew();
$this->pourInCup();
$this->addContents();
}
}
そして、この抽象クラスを継承したサブクラス(CoffeeクラスとTeaクラス)は、それぞれ独自の処理を記述するだけです。
<?php
require_once 'CaffeineBeverage.php';
class Coffee extends CaffeineBeverage {
//それぞれのクラス独自の処理のみを実装する
protected function brew() {
echo "コーヒー豆を挽き、ドリップします\n";
}
protected function addContents() {
echo "砂糖とミルクを足します\n";
}
}
<?php
require_once 'CaffeineBeverage.php';
class Tea extends CaffeineBeverage {
//それぞれのクラス独自の処理のみを実装する
protected function brew() {
echo "ティーバッグを浸します\n";
}
protected function addContents() {
echo "レモンを足します\n";
}
}
どうでしょう?テンプレートメソッドを適用させたことによって、CoffeeクラスとTeaクラスがだいぶスッキリして見えませんか?
飲み物が増えたとしても、CaffeineBeverage
クラスを継承して独自の処理だけ付け足せば良いので、とても楽ですね。
ただ、作り方が全く違ってたり、独自のステップ(例えば30分蒸らすとか)がある場合は、テンプレートメソッドの管轄外から外れてしまうので出来ません。
参考書籍
Author And Source
この問題について(TemplateMethodパターンをPHPで書いてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/27ma4_ryusei/items/860e74c1fde3210deea1著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .