Я хочу реализовать шаблон Stategy, используя Closures в php. Основным преимуществом использования замыкания является уменьшение количества шаблонов и кода, необходимых для создания дополнительных классов. Обычно шаблон выглядит так:
interface StateDiscountCalculatorInterface
{
public function calculateDiscount($amount);
}
class NewYorkStateStrategy implement StateDiscountCalculatorInterface
{
public function calculateDiscount($amount)
{
// .... about 20 lines of code
}
}
class CaliforniaStateStrategy implement StateTaxCalculatorInterface
{
public function calculateDiscount($amount)
{
// .... about 20 lines of code that's different from New York State Strategy
}
}
class stateTaxContext
{
private $stategy;
public function setStrategy(StateDiscountCalculatorInterface $strategy)
{
$this->strategy = $strategy;
}
public function getDiscount(array $amount)
{
return $this->strategy->calculateDiscount($amount);
}
}
Версия ниже с замыканием, реализующим функциональный интерфейс php. Это правильный способ сделать это?
interface StateDiscountCalculatorInterface
{
public function calculateDiscount($amount);
}
class stateTaxContext
{
private $newYorkStateStrategy;
private $californiaStateStrategy;
private $state;
public function __construct()
{
$this->newYorkStateStrategy = function () implements StateDiscountCalculatorInterface {
...NewYorkStateStrategy class is replaced with code here
};
$this->californiaStateStrategy = function () implements StateDiscountCalculatorInterface {
...CaliforniaStateStrategy class is replaced with code here
};
}
public function getDiscount(array $amount)
{
if($this->state==='california')
{
$this->californiaStateStrategy->calculateDiscount($amount);
}
}
}
Я не эксперт по шаблонам проектирования, но, на мой взгляд, одним из лучших подходов для реализации шаблона стратегии будет следующий — вы можете сохранить интерфейс & классы стратегии, как они есть, но реализуют контекст следующим образом:
class StateTaxContext
{
private $state;
public function setState(StateDiscountCalculatorInterface $state)
{
$this->state = $state;
}
public function getDiscount(array $amount)
{
return $this->state->->calculateDiscount($amount);
}
}
И тогда вы можете использовать этот шаблон везде в вашем коде, например так:
$context = new StateTaxContext();
// Calculate NY discount?
$context->setState(new NewYorkStateStrategy());
$data = $context->getDiscount($amount);
// Calculate California discount?
$context->setState(new CaliforniaStateStrategy());
$data = $context->getDiscount($amount);
Других решений пока нет …