ジョークには次のようなものがあります: 象を冷蔵庫に入れるのに何歩かかりますか?
1. 冷蔵庫を開けます
2. 象を中に詰めます
同様に、ライオンを冷蔵庫に入れるには何ステップかかりますか?
1. 冷蔵庫を開けます
2. ライオンを中に詰めます
3. 冷蔵庫を閉めます
上記の例では、2 つの方法は実際には同じステップを持っていますが、具体的な実装が少し異なることがわかりましたか?つまり、これら 2 種類の動作はステップ テンプレートを共有できます。これは、今回説明するデザイン パターン、つまりテンプレート デザイン パターンにつながります。
テンプレート設計パターンの原理は、以下に示すような UML クラス図で表すことができます:
具体的なコード例:
LockAnimal.php
<?php /** * 将动物锁进冰箱里抽象类 * @author ben * */ abstract class LockAnimal{ /** * 模板方法,使用final关键词防止子类覆盖 */ public final function lock(){ $this->open(); $this->push(); $this->close(); } /** * 打开冰箱 */ abstract function open(); /** * 将动物推进冰箱 */ abstract function push(); /** * 关上冰箱 */ abstract function close(); }
<?php /** * 将狮子锁进冰箱里 * @author ben * */ require_once 'LockAnimal.php'; class LockElephant extends LockAnimal{ /** * (non-PHPdoc) * @see LockAnimal::open() */ public function open(){ echo "in order to lock an elephant into a fridge, you need to open the fridge first<br />"; } /** * (non-PHPdoc) * @see LockAnimal::push() */ public function push(){ echo "i'm pushing the elephant<br />"; } /** * (non-PHPdoc) * @see LockAnimal::close() */ public function close(){ echo "finally, now i can close the fridge<br />"; } }
<?php /** * 将狮子锁进冰箱里 * @author ben * */ require_once 'LockAnimal.php'; class LockLion extends LockAnimal{ /** * (non-PHPdoc) * @see LockAnimal::open() */ public function open(){ echo "in order to lock an lion into a fridge, you need to open the fridge first<br />"; } /** * (non-PHPdoc) * @see LockAnimal::push() */ public function push(){ echo "i'm pushing the lion<br />"; } /** * (non-PHPdoc) * @see LockAnimal::close() */ public function close(){ echo "finally, now i can close the fridge<br />"; } }
LockAnimal.php
<?php /** * 将动物锁进冰箱里抽象类 * @author ben * */ abstract class LockAnimal{ /** * 模板方法,使用final关键词防止子类覆盖 */ public final function lock(){ $this->open(); if($this->needAnesthetic()){ $this->anesthetic(); } $this->push(); $this->close(); } /** * 打开冰箱 */ abstract function open(); /** * 是否需要麻醉 */ protected function needAnesthetic(){ return false; } protected function anesthetic(){ echo "anestheticing the animal"; } /** * 将动物推进冰箱 */ abstract function push(); /** * 关上冰箱 */ abstract function close(); }
<?php /** * 将狮子锁进冰箱里 * @author ben * */ require_once 'LockAnimal.php'; class LockElephant extends LockAnimal{ /** * (non-PHPdoc) * @see LockAnimal::open() */ public function open(){ echo "in order to lock an elephant into a fridge, you need to open the fridge first<br />"; } /** * (non-PHPdoc) * @see LockAnimal::push() */ public function push(){ echo "i'm pushing the elephant<br />"; } /** * (non-PHPdoc) * @see LockAnimal::close() */ public function close(){ echo "finally, now i can close the fridge<br />"; } }
<?php /** * 将狮子锁进冰箱里 * @author ben * */ require_once 'LockAnimal.php'; class LockLion extends LockAnimal{ /** * (non-PHPdoc) * @see LockAnimal::open() */ public function open(){ echo "in order to lock an lion into a fridge, you need to open the fridge first<br />"; } protected function needAnesthetic(){ return true; } protected function anesthetic(){ echo "anestheticing the lion<br />"; } /** * (non-PHPdoc) * @see LockAnimal::push() */ public function push(){ echo "i'm pushing the lion<br />"; } /** * (non-PHPdoc) * @see LockAnimal::close() */ public function close(){ echo "finally, now i can close the fridge<br />"; } }
<?php require_once 'LockElephant.php'; require_once 'LockLion.php'; $elephant = new LockElephant(); $lion = new LockLion(); $elephant->lock(); $lion->lock();