どうも、今月ブログ更新をサボり気味で後悔してます。
「ブログ続けてるのすごい」って言われて嬉しかったので、
更新ちゃんと頑張ります。
遡ってみると2017年1月からブログを始めて早2年経ってました。
累計113記事でした。
\目標、1000記事/
今回は、TemplateMethodについてです。
TemplateMethodとは?
メソッドにおけるアルゴリズムの骨組みを定義し、
いくつかの手順をサブクラスに先送りします。
→ アルゴリズムとなる一連の手順(メソッド)を
定義するメソッド(テンプレート)があり、
その一連の手順の中のメソッドの1つ以上を
抽象メソッドとして定義し、
サブクラスがそれを実装する
クラス図
コード
abstract class AbstractClass { public function templateMethod(): void { $this->primitiveOperation1(); $this->primitiveOperation2(); } //それぞれ異なる手順→サブクラスにまかせる abstract public function primitiveOperation1(); public function primitiveOperation2(): void { //共通の手順 } }
class ConcreteClass extends AbstractClass { public function primitiveOperation1(): void { // TODO: Implement primitiveOperation1() method. } }
いざ、実装!
Head Firstデザインパターンの具体例では、
コーヒーと紅茶の作り方がでてきました。
レシピ
▶︎コーヒーの作り方 1.お湯を沸かす 2.フィルターをセットして淹れる 3.コップにコーヒーを注ぐ 4.ミルクや砂糖を加える ▶︎紅茶の作り方 1.お湯を沸かす 2.ティパックをセットしてお湯をいれる 3.レモンをいれる 4.コップに注ぐ
ざっくりみると、コーヒーと紅茶の作り方は似ているので、
1~4の一連の手順をテンプレートメソッドとしてスーパークラスに定義し、
「1.お湯を沸かす」の部分は共通化できるので、スーパークラスで実装します。
コーヒーと紅茶で異なる部分はサブクラスで実装します。
実際のコードはこちら↓
[kin29/HeadFirstDezaPata]
クラス図
コード
abstract class CaffeineBeverage { public function prepareRecipe(): void { $this->boilWater(); $this->brew(); $this->pourInCup(); $this->addCondiments(); } abstract public function brew(): void; abstract public function addCondiments(): void; public function boilWater(): void { echo "お湯を沸かします\n"; } public function pourInCup(): void { echo "カップに注ぎます\n"; } }
class Coffee extends CaffeineBeverage { public function __toString(): string { return "--- コーヒーのレシピ ---\n"; } public function brew(): void { echo "フィルターでコーヒをドリップします\n"; } public function addCondiments(): void { echo "砂糖とミルクを追加します\n"; } }
class Tea extends CaffeineBeverage { public function __toString(): string { return "--- 紅茶のレシピ ---\n"; } public function brew(): void { echo "紅茶を浸します\n"; } public function addCondiments(): void { echo "レモンを追加します\n"; } }
$ php src/TemplateMethod/main.php --- コーヒーのレシピ --- お湯を沸かします フィルターでコーヒをドリップします カップに注ぎます 砂糖とミルクを追加します --- 紅茶のレシピ --- お湯を沸かします 紅茶を浸します カップに注ぎます レモンを追加します
メリット
・共通メソッドの変更が必要となった場合、
スーパクラスの変更のみでいい。
・スーパクラスで骨組みを定義しているので、
新しいカフェインクラスの追加が必要になった場合(例えばココアとか?)、
実装がしやすい
令和もがんばろーっっと