Шаблонный метод (англ. Template method ) — поведенческий шаблон проектирования, определяющий скелет алгоритма,
перекладывая ответственность за некоторые его шаги на подклассы. Позволяет подклассам переопределять шаги алгоритма,
не меняя его общей структуры.
Другими словами, это каркас алгоритма, который хорошо подходит для библиотек (в фреймворках, например).
Пользователь просто реализует уточняющие методы, а суперкласс делает всю основную работу.
Это простой способ изолировать логику в конкретные классы и уменьшить копипаст,
поэтому вы повсеместно встретите его в том или ином виде.
BeachJourney.php
<?php
namespace DesignPatterns\Behavioral\TemplateMethod ;
/**
* Class BeachJourney
* @package DesignPatterns\Behavioral\TemplateMethod
*/
class BeachJourney extends Journey
{
/**
* @return string
*/
protected function enjoyVacation (): string
{
return "Swimming and sun-bathing" ;
}
}
CityJourney.php
<?php
namespace DesignPatterns\Behavioral\TemplateMethod ;
/**
* Class CityJourney
* @package DesignPatterns\Behavioral\TemplateMethod
*/
class CityJourney extends Journey
{
/**
* @return string
*/
protected function enjoyVacation (): string
{
return "Eat, drink, take photos and sleep" ;
}
/**
* @return string
*/
protected function buyGift (): string
{
return "Buy a gift" ;
}
}
Journey.php
<?php
namespace DesignPatterns\Behavioral\TemplateMethod ;
/**
* Class Journey
* @package DesignPatterns\Behavioral\TemplateMethod
*/
abstract class Journey
{
/**
* @var string[]
*/
private $thingsToDo = [];
/**
* @return void
*/
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 ();
}
/**
* @return string
*/
abstract protected function enjoyVacation (): string ;
/**
* @return string|null
*/
protected function buyGift ()
{
return null ;
}
/**
* @return string
*/
private function buyAFlight (): string
{
return 'Buy a flight ticket' ;
}
/**
* @return string
*/
private function takePlane (): string
{
return 'Taking the plane' ;
}
/**
* @return string[]
*/
public function getThingsToDo (): array
{
return $this -> thingsToDo ;
}
}
Test case:
TemplateMethodTest.php
<?php
namespace DesignPatterns\Tests\Behavioral\TemplateMethod ;
use DesignPatterns\Behavioral\TemplateMethod\BeachJourney ;
use DesignPatterns\Behavioral\TemplateMethod\CityJourney ;
class TemplateMethodTest extends \ PHPUnit_Framework_TestCase
{
public function testCanGetOnVacationOnTheBeach ()
{
$beachJourney = new BeachJourney ();
$beachJourney -> takeATrip ();
$this -> assertEquals (
[ 'Buy a flight ticket' , 'Taking the plane' , 'Swimming and sun-bathing' , 'Taking the plane' ],
$beachJourney -> getThingsToDo ()
);
}
public function testCanGetOnAJourneyToACity ()
{
$beachJourney = new CityJourney ();
$beachJourney -> takeATrip ();
$this -> assertEquals (
[
'Buy a flight ticket' ,
'Taking the plane' ,
'Eat, drink, take photos and sleep' ,
'Buy a gift' ,
'Taking the plane'
],
$beachJourney -> getThingsToDo ()
);
}
}