PHP中的策略设计模式实例

60 阅读1分钟

当我们需要根据运行时提供的信息来执行一些逻辑时,就会用到策略模式。它在技术上与条件语句相同,如if..else,select .. case 等。但属于OOP风格。它是SOLID的 "开放/封闭原则"的一个很好的例子。使用这种模式的方法有很多,但我只想说说最常见的变化。

消息发布策略

类别

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);
    }
}

用法

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;

结果

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

主页画家策略

类别

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();
    }
}

使用方法

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;

结果

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

数字处理器策略

类别

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;
    }
}

使用方法

require_once 'NumberProcessor.php';

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

echo $numberProcessor->run(4);

echo PHP_EOL;

结果

$ php oop/NumberProcessor/index.php 
64