模板方法是一種行為設(shè)計(jì)模式。
你可能已經(jīng)遇到過很多次了。它的思想是讓這個(gè)抽象模板的子類【完成】算法的行為策略。
也就是【好萊塢原則】:【別打給我們,我們打給你】。這個(gè)類不是由子類調(diào)用的,而是由相反的子類調(diào)用的。怎么樣?當(dāng)然是抽象的。
換句話說,這是一個(gè)算法框架,非常適合框架庫。用戶只需要實(shí)現(xiàn)一個(gè)方法,超類就可以完成這項(xiàng)工作。
它是解耦具體類和減少復(fù)制黏貼的一種簡單方法,這就是為什么你會(huì)發(fā)現(xiàn)它無處不在。
Journey.php
<?php declare(strict_types=1); namespace DesignPatterns\Behavioral\TemplateMethod; abstract class Journey { /** * @var string[] */ private array $thingsToDo = []; /** * This is the public service provided by this class and its subclasses. * Notice it is final to "freeze" the global behavior of algorithm. * If you want to override this contract, make an interface with only takeATrip() * and subclass it. */ final public function takeATrip() { $this->thingsToDo[] = $this->buyAFlight(); $this->thingsToDo[] = $this->takePlane(); $this->thingsToDo[] = $this->enjoyVacation(); $buyGift = $this->buyGift(); if ($buyGift !== null) { $this->thingsToDo[] = $buyGift; } $this->thingsToDo[] = $this->takePlane(); } /** * This method must be implemented, this is the key-feature of this pattern. */ abstract protected function enjoyVacation(): string; /** * This method is also part of the algorithm but it is optional. * You can override it only if you need to */ protected function buyGift(): ?string { return null; } private function buyAFlight(): string { return 'Buy a flight ticket'; } private function takePlane(): string { return 'Taking the plane'; } /** * @return string[] */ public function getThingsToDo(): array { return $this->thingsToDo; } }
BeachJourney.php
<?php declare(strict_types=1); namespace DesignPatterns\Behavioral\TemplateMethod; class BeachJourney extends Journey { protected function enjoyVacation(): string { return "Swimming and sun-bathing"; } }
CityJourney.php
<?php declare(strict_types=1); namespace DesignPatterns\Behavioral\TemplateMethod; class CityJourney extends Journey { protected function enjoyVacation(): string { return "Eat, drink, take photos and sleep"; } protected function buyGift(): ?string { return "Buy a gift"; } }
Tests/JourneyTest.php
<?php declare(strict_types=1); namespace DesignPatterns\Behavioral\TemplateMethod\Tests; use DesignPatterns\Behavioral\TemplateMethod\BeachJourney; use DesignPatterns\Behavioral\TemplateMethod\CityJourney; use PHPUnit\Framework\TestCase; class JourneyTest extends TestCase { public function testCanGetOnVacationOnTheBeach() { $beachJourney = new BeachJourney(); $beachJourney->takeATrip(); $this->assertSame( ['Buy a flight ticket', 'Taking the plane', 'Swimming and sun-bathing', 'Taking the plane'], $beachJourney->getThingsToDo() ); } public function testCanGetOnAJourneyToACity() { $cityJourney = new CityJourney(); $cityJourney->takeATrip(); $this->assertSame( [ 'Buy a flight ticket', 'Taking the plane', 'Eat, drink, take photos and sleep', 'Buy a gift', 'Taking the plane' ], $cityJourney->getThingsToDo() ); } }
更多建議: