テンプレート メソッド パターンは、メソッド内のアルゴリズムの骨格を定義し、一部のステップをサブクラスに延期します。テンプレート メソッドを使用すると、アルゴリズムの構造を変更せずに、サブクラスでアルゴリズムの特定のステップを再定義できます。
テンプレート メソッド パターンは、サブクラスがアルゴリズム スケルトンを変更しないようにメイン メソッドを Final メソッドとして定義し、サブクラスが実装する必要があるメソッドを抽象メソッドとして定義します。通常のメソッド (最終的な変更や抽象的な変更を行わない) はフックと呼ばれます。
Journey.php
<?phpnamespace DesignPatterns\Behavioral\TemplateMethod;abstract class Journey{ /** * 该方法是父类和子类提供的公共服务 * 注意到方法前加了final,意味着子类不能重写该方法 */ final public function takeATrip() { $this->buyAFlight(); $this->takePlane(); $this->enjoyVacation(); $this->buyGift(); $this->takePlane(); } /** * 该方法必须被子类实现, 这是模板方法模式的核心特性 */ abstract protected function enjoyVacation(); /** * 这个方法也是算法的一部分,但是是可选的,只有在需要的时候才去重写它 */ protected function buyGift() { } /** * 子类不能访问该方法 */ private function buyAFlight() { echo "Buying a flight\n"; } /** * 这也是个final方法 */ final protected function takePlane() { echo "Taking the plane\n"; }}
BeachJourney.php
<?phpnamespace DesignPatterns\Behavioral\TemplateMethod;/** * BeachJourney类(在海滩度假) */class BeachJourney extends Journey{ protected function enjoyVacation() { echo "Swimming and sun-bathing\n"; }}
CityJourney.php
<?phpnamespace DesignPatterns\Behavioral\TemplateMethod;/** * CityJourney类(在城市中度假) */class CityJourney extends Journey{ protected function enjoyVacation() { echo "Eat, drink, take photos and sleep\n"; }}
Tests/JourneyTest.php
<?phpnamespace DesignPatterns\Behavioral\TemplateMethod\Tests;use DesignPatterns\Behavioral\TemplateMethod;/** * JourneyTest测试所有的度假 */class JourneyTest extends \PHPUnit_Framework_TestCase{ public function testBeach() { $journey = new TemplateMethod\BeachJourney(); $this->expectOutputRegex('#sun-bathing#'); $journey->takeATrip(); } public function testCity() { $journey = new TemplateMethod\CityJourney(); $this->expectOutputRegex('#drink#'); $journey->takeATrip(); } /** * 在PHPUnit中如何测试抽象模板方法 */ public function testLasVegas() { $journey = $this->getMockForAbstractClass('DesignPatterns\Behavioral\TemplateMethod\Journey'); $journey->expects($this->once()) ->method('enjoyVacation') ->will($this->returnCallback(array($this, 'mockUpVacation'))); $this->expectOutputRegex('#Las Vegas#'); $journey->takeATrip(); } public function mockUpVacation() { echo "Fear and loathing in Las Vegas\n"; }}
テンプレート メソッド パターンは、継承に基づいたコード再利用技術であり、テンプレート メソッド パターンの構造と使用法もオブジェクト指向設計の中核の 1 つです。テンプレート メソッド パターンでは、親クラスに同じコードを配置し、異なるサブクラスに異なるメソッド実装を配置できます。
テンプレート メソッド パターンでは、抽象クラスを準備し、ロジックの一部を具象メソッドと具象コンストラクターの形式で実装してから、サブクラスが残りのロジックを実装できるようにいくつかの抽象メソッドを宣言する必要があります。異なるサブクラスは、これらの抽象メソッドを異なる方法で実装できるため、残りのロジックの実装も異なります。これがテンプレート メソッド パターンの目的です。テンプレート メソッド パターンは、オブジェクト指向の多くの重要なアイデアを具体化しており、頻繁に使用されるパターンです。