strategy Стратегия (англ. Strategy) — поведенческий шаблон проектирования, предназначенный для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Это позволяет выбирать алгоритм путём определения соответствующего класса. Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов-клиентов, которые его используют.

  • Strategies
    • AddStrategy.php
                    
      <?php
      
      namespace DesignPatterns\Behavioral\Strategy\Strategies;
      
      /**
       * Class AddStrategy
       * @package DesignPatterns\Behavioral\Strategy\Strategies
       */
      class AddStrategy implements StrategyInterface
      {
          /**
           * @param int $x
           * @param int $y
           *
           * @return int
           */
          public function algorithm(int $x, int $y): int
          {
              return $x + $y;
          }
      }
      
                    
    • MultiplyStrategy.php
                    
      <?php
      
      namespace DesignPatterns\Behavioral\Strategy\Strategies;
      
      /**
       * Class MultiplyStrategy
       * @package DesignPatterns\Behavioral\Strategy\Strategies
       */
      class MultiplyStrategy implements StrategyInterface
      {
          /**
           * @param int $x
           * @param int $y
           *
           * @return int
           */
          public function algorithm(int $x, int $y): int
          {
              return $x * $y;
          }
      }
      
                    
    • StrategyInterface.php
                    
      <?php
      
      namespace DesignPatterns\Behavioral\Strategy\Strategies;
      
      /**
       * Interface StrategyInterface
       * @package DesignPatterns\Behavioral\Strategy\Strategies
       */
      interface StrategyInterface
      {
          /**
           * @param int $x
           * @param int $y
           *
           * @return int
           */
          public function algorithm(int $x, int $y): int;
      }
      
                    
    • SubtractStrategy.php
                    
      <?php
      
      namespace DesignPatterns\Behavioral\Strategy\Strategies;
      
      /**
       * Class SubtractStrategy
       * @package DesignPatterns\Behavioral\Strategy\Strategies
       */
      class SubtractStrategy implements StrategyInterface
      {
          /**
           * @param int $x
           * @param int $y
           *
           * @return int
           */
          public function algorithm(int $x, int $y): int
          {
              return $x - $y;
          }
      }
      
                    
  • SimpleCalculator.php
                  
    <?php
    
    namespace DesignPatterns\Behavioral\Strategy;
    
    use DesignPatterns\Behavioral\Strategy\Strategies\StrategyInterface;
    
    /**
     * Class SimpleCalculator
     * @package DesignPatterns\Behavioral\Strategy
     */
    class SimpleCalculator
    {
        /**
         * @var int
         */
        private $x;
    
        /**
         * @var int
         */
        private $y;
    
        /**
         * @var StrategyInterface
         */
        private $strategy;
    
        /**
         * SimpleCalculator constructor.
         *
         * @param int $x
         * @param int $y
         */
        public function __construct(int $x, int $y)
        {
            $this->x = $x;
            $this->y = $y;
        }
    
        /**
         * @param StrategyInterface $strategy
         *
         * @return void
         */
        public function setStrategy(StrategyInterface $strategy)
        {
            $this->strategy = $strategy;
        }
    
        /**
         * @return int
         */
        public function execute(): int
        {
            return $this->strategy->algorithm($this->x, $this->y);
        }
    }
    
                  
  • Test case:

    StrategyTest.php
      
    <?php
    
    namespace DesignPatterns\Tests\Behavioral\Strategy;
    
    use DesignPatterns\Behavioral\Strategy\SimpleCalculator;
    use DesignPatterns\Behavioral\Strategy\Strategies\AddStrategy;
    use DesignPatterns\Behavioral\Strategy\Strategies\MultiplyStrategy;
    use DesignPatterns\Behavioral\Strategy\Strategies\SubtractStrategy;
    use PHPUnit_Framework_TestCase;
    
    class StrategyTest extends PHPUnit_Framework_TestCase
    {
        public function provideIntegersForAdd()
        {
            return [
                [2, 3, 5],
                [8, 3, 11],
                [-3, 5, 2],
                [23, -3, 20],
                [-42, -20, -62],
            ];
        }
    
        public function provideIntegersForSub()
        {
            return [
                [2, 3, -1],
                [8, 3, 5],
                [-3, 5, -8],
                [23, -3, 26],
                [-42, -20, -22],
            ];
        }
    
        public function provideIntegersForMulti()
        {
            return [
                [2, 3, 6],
                [8, 3, 24],
                [-3, 5, -15],
                [23, -3, -69],
                [-42, -20, 840],
            ];
        }
    
        /**
         * @dataProvider provideIntegersForAdd
         *
         * @param int $x
         * @param int $y
         * @param int $expected
         */
        public function testSimpleCalculatorWithAddStrategy(int $x, int $y, int $expected)
        {
            $simpleCalculator = new SimpleCalculator($x, $y);
            $simpleCalculator->setStrategy(new AddStrategy());
    
            $this->assertEquals($expected, $simpleCalculator->execute());
        }
    
        /**
         * @dataProvider provideIntegersForSub
         *
         * @param int $x
         * @param int $y
         * @param int $expected
         */
        public function testSimpleCalculatorWithSubtractStrategy(int $x, int $y, int $expected)
        {
            $simpleCalculator = new SimpleCalculator($x, $y);
            $simpleCalculator->setStrategy(new SubtractStrategy());
    
            $this->assertEquals($expected, $simpleCalculator->execute());
        }
    
        /**
         * @dataProvider provideIntegersForMulti
         *
         * @param int $x
         * @param int $y
         * @param int $expected
         */
        public function testSimpleCalculatorWithMultiplyStrategy(int $x, int $y, int $expected)
        {
            $simpleCalculator = new SimpleCalculator($x, $y);
            $simpleCalculator->setStrategy(new MultiplyStrategy());
    
            $this->assertEquals($expected, $simpleCalculator->execute());
        }
    }