目的
模板方法模式是一种让抽象模板的子类「完成」一系列算法的行为策略。
众所周知的「好莱坞原则」:「不要打电话给我们,我们会打电话给你」。这个类不是由子类调用的,而是以相反的方式。怎么做?当然很抽象啦!
换而言之,它是一种非常适合框架库的算法骨架。用户只需要实现子类的一种方法,其父类便可去搞定这项工作了。
这是一种分离具体类的简单办法,且可以减少复制粘贴,这也是它常见的原因。
UML图
代码
- Journey.php
<?php
namespace DesignPatterns\Behavioral\TemplateMethod;
abstract class Journey
{
/**
* @var string[]
*/
private $thingsToDo = [];
/**
* 这是当前类及其子类提供的公共服务
* 注意,它「冻结」了全局的算法行为
* 如果你想重写这个契约,只需要实现一个包含 takeATrip() 方法的接口
*/
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();
}
/**
* 这个方法必须要实现,它是这个模式的关键点
*/
abstract protected function enjoyVacation(): string;
/**
* 这个方法是可选的,也可能作为算法的一部分
* 如果需要的话你可以重写它
*
* @return null|string
*/
protected function buyGift()
{
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
namespace DesignPatterns\Behavioral\TemplateMethod;
class BeachJourney extends Journey
{
protected function enjoyVacation(): string
{
return "Swimming and sun-bathing";
}
}
- CityJourney.php
<?php
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
namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
use DesignPatterns\Behavioral\TemplateMethod;
use PHPUnit\Framework\TestCase;
class JourneyTest extends TestCase
{
public function testCanGetOnVacationOnTheBeach()
{
$beachJourney = new TemplateMethod\BeachJourney();
$beachJourney->takeATrip();
$this->assertEquals(
[‘Buy a flight ticket‘, ‘Taking the plane‘, ‘Swimming and sun-bathing‘, ‘Taking the plane‘],
$beachJourney->getThingsToDo()
);
}
public function testCanGetOnAJourneyToACity()
{
$cityJourney = new TemplateMethod\CityJourney();
$cityJourney->takeATrip();
$this->assertEquals(
[
‘Buy a flight ticket‘,
‘Taking the plane‘,
‘Eat, drink, take photos and sleep‘,
‘Buy a gift‘,
‘Taking the plane‘
],
$cityJourney->getThingsToDo()
);
}
}
PHP 互联网架构师 50K 成长指南+行业问题解决总纲(持续更新)
面试10家公司,收获9个offer,2020年PHP 面试问题
★如果喜欢我的文章,想与更多资深开发者一起交流学习的话,获取更多大厂面试相关技术咨询和指导,欢迎加入我们的群啊,暗号:phpzh(君羊号码856460874)。
内容不错的话希望大家支持鼓励下点个赞/喜欢,欢迎一起来交流;另外如果有什么问题 建议 想看的内容可以在评论提出