Strateji modeli, çalışma zamanında sağlanan bilgilere dayanarak bazı mantıkları yürütmemiz gerektiğinde kullanılır. Teknik olarak if..else, select .. case vs. gibi koşullu ifadelerle aynıdır ama OOP stilinde. SOLID'in Açık/Kapalı Prensibi için harika bir örnektir. Bu modeli kullanmanın birkaç yolu olabilir, ancak ben en yaygın varyasyonlara değineceğim.


Mesaj yayınlama stratejisi


Classlar


class MessagePublisher
{
private $strategy;

public function __construct(StrategyInterface $strategy)
{
$this->strategy = $strategy;
}

public function publish(string $message): string
{
return $this->strategy->process($message);
}
}

interface StrategyInterface
{
public function process(string $message): string;
}

class FacebookStrategy implements StrategyInterface
{
public function process(string $message): string
{
return sprintf('Message "%s" published on Facebook.', $message);
}
}

class TwitterStrategy implements StrategyInterface
{
public function process(string $message): string
{
return sprintf('Message "%s" published on Twitter.', $message);
}
}

Kullanımı


require_once 'MessagePublisher.php';

$messagePublisher = new MessagePublisher(new FacebookStrategy());
echo $messagePublisher->publish('Hello');

echo PHP_EOL;

$messagePublisher = new MessagePublisher(new TwitterStrategy());
echo $messagePublisher->publish('Hello');

echo PHP_EOL;

Sonuç


$ php oop/MessagePublisher/index.php 
Message "Hello" published on Facebook.
Message "Hello" published on Twitter.

Ev boyama stratejisi


Classlar


class HomePainter
{
private $painters;

public function __construct(array $painters)
{
$this->painters = $painters;
}

public function start(Home $home, string $section): ?string
{
/** @var StrategyInterface $painter */
foreach ($this->painters as $painter) {
if ($painter->canPaint($section)) {
return $painter->paint($home);
}
}

return null;
}
}

class Home
{
public function doors(): string
{
return 'Doors painted yellow';
}

public function steps(): string
{
return 'Steps painted blue';
}
}

interface StrategyInterface
{
public function canPaint(string $section): bool;

public function paint(Home $home): string;
}

class YellowPainterStrategy implements StrategyInterface
{
public function canPaint(string $section): bool
{
return 'doors' === $section;
}

public function paint(Home $home): string
{
return $home->doors();
}
}

class BluePainterStrategy implements StrategyInterface
{
public function canPaint(string $section): bool
{
return 'steps' === $section;
}

public function paint(Home $home): string
{
return $home->steps();
}
}

Kullanımı


require_once 'HomePainter.php';

$home = new Home();

$homePainter = new HomePainter([
new YellowPainterStrategy(),
new BluePainterStrategy(),
]);

echo $homePainter->start($home, 'doors');

echo PHP_EOL;

echo $homePainter->start($home, 'steps');

echo PHP_EOL;

Sonuç


$ php oop/HomePainter/index.php 
Doors painted yellow
Steps painted blue

Numara işleme stratejisi


Classlar


class NumberProcessor
{
private $strategies;

public function addProcessor(StrategyInterface $strategy)
{
$this->strategies[] = $strategy;

return $this;
}

public function run(int $number): int
{
/** @var StrategyInterface $strategy */
foreach ($this->strategies as $strategy) {
$number = $strategy->process($number);
}

return $number;
}
}

interface StrategyInterface
{
public function process(int $number): int;
}

class SumStrategy implements StrategyInterface
{
public function process(int $number): int
{
return $number + $number;
}
}

class MultiplyStrategy implements StrategyInterface
{
public function process(int $number): int
{
return $number * $number;
}
}

Kullanımı


require_once 'NumberProcessor.php';

$numberProcessor = new NumberProcessor();
$numberProcessor
->addProcessor(new SumStrategy())
->addProcessor(new MultiplyStrategy());

echo $numberProcessor->run(4);

echo PHP_EOL;

Sonuç


$ php oop/NumberProcessor/index.php 
64