Идеята на този шаблон е да осигури гъвкав начин за задаване и използване на различни алгоритми (ще ги наречем „стратегии“) с огледа на лесната им взаимозаменяемост.
Този шаблон пресъздава SOLID принципът Open-Close Principle.
Характерно за този шаблон е, че се използва принципът Composition, а не Inheritance, тоест отделните „стратегии“ не трябва да бъдат наследявани, а да бъдат добавяни като пропърти на даден централен клас, който ще наричаме Контекстен.
По-просто казано, дефинираме си различни класове, имплементиращи общ интерфейс с оглед на това да бъдат взаимозаменяеми, като в даденият случай, всеки клас е една отделна стратегия.
Пример:
interface IStrategy { public function showTitle(Book $oBook) : string; } class StrategyCaps implements IStrategy { public function showTitle(Book $oBook) : string { $title = $oBook->getTitle(); return strtoupper($title); } } class StrategyExclaim implements IStrategy { public function showTitle(Book $oBook) : string { $title = $oBook->getTitle(); return str_replace(' ', '!', $title); } } class StrategyStars implements IStrategy { public function showTitle(Book $oBook) : string { $title = $oBook->getTitle(); return str_replace(' ', '*', $title); } } class StrategyContext { private IStrategy $strategy; // Instance of one of the above classes// 1. Set desired strategy in a private property
public function __construct(IStrategy $oStrategy)
{
$this->strategy = $oStrategy;
}
// 2. Perform selected strategy method
public function showBookTitle(Book
$book): string
{
return $this->strategy->showTitle($book);
}
} class Book { private string $author, $title;public function __construct(string $title_in, string $author_in)
{
$this->author = $author_in;
$this->title = $title_in;
}
public function getAuthor(): string
{
return $this->author;
}
public function getTitle(): string
{
return $this->title;
}
public function getAuthorAndTitle(): string
{
return $this->getTitle() . ' by ' . $this->getAuthor();
}
} // Предварително създаваме набор от различни стратегии $strategyContextC = new StrategyContext(new StrategyCaps()); $strategyContextE = new StrategyContext(new StrategyExclaim()); $strategyContextS = new StrategyContext(new StrategyStars()); // Върху този обект ще прилагаме различните стратегии $book = new Book('Nemili Nedragi', 'Ivan Vazov'); echo "\n\ntest 1 - show name context C \n"; echo $strategyContextC->showBookTitle($book); echo "\n\n"; echo "\n\ntest 2 - show name context E \n"; echo $strategyContextE->showBookTitle($book); echo "\n\n"; echo "\n\ntest 3 - show name context S \n"; echo $strategyContextS->showBookTitle($book); echo "\n\n"; // Може и без контекст $strategyContextC1 = new StrategyCaps(); echo $strategyContextC1->showTitle($book);
Виждат се отделните „стратегии“, вижда се обектът, върху който ще ги прилагаме.
Вижда се че може директно да прилагаме желаната стратегия, като създадем обект от нейният клас и и подадем обектът, върху ще се прилага стратегията.
Може и през т.н. „контекст“, ако например искаме да капсулираме допълнителна логика, която да обработи подадения обект.