command Команда (англ. Command) належить до класу шаблонів поведінки. Команда є деякою дією та її параметрами. Суть шаблону полягає в тому, щоб відокремити ініціатора та одержувача команди.

Припустимо, у нас є об’єкти Вимикач (Командир) та Лампа (Виконавець). Цей шаблон використовує реалізацію інтерфейсу CommandInterface, щоб викликати якийсь метод Виконавця, використовуючи для цього відомий Командирові метод execute(). Командир просто знає, що потрібно викликати метод execute() для обробки команди клієнта, не розбираючись у деталях реалізації Виконавця. Виконавець відокремлений від команди.

  • CommandInterface.php
                  
    <?php
    
    namespace DesignPatterns\Behavioral\Command;
    
    /**
     * Interface CommandInterface
     * @package DesignPatterns\Behavioral\Command
     */
    interface CommandInterface
    {
        public function execute();
    }
    
                  
  • CommandRegistry.php
                  
    <?php
    
    namespace DesignPatterns\Behavioral\Command;
    
    use Countable;
    use RuntimeException;
    
    class CommandRegistry implements Countable
    {
        /**
         * @var CommandInterface[]
         */
        private $registry = [];
    
        /**
         * @param string $type
         * @param CommandInterface $command
         */
        public function add(CommandInterface $command, string $type)
        {
            $this->registry[$type] = $command;
        }
    
        /**
         * @param string $type
         * @return CommandInterface
         * @throws RuntimeException
         */
        public function get($type)
        {
            if (!isset($this->registry[$type])) {
                throw new RuntimeException('Cannot find command ' . $type);
            }
    
            return $this->registry[$type];
        }
    
        public function count()
        {
            return count($this->registry);
        }
    }
    
                  
  • Lamp.php
                  
    <?php
    
    namespace DesignPatterns\Behavioral\Command;
    
    class Lamp
    {
        public function turnOn()
        {
            return 'I\'m bright and cheerful light.';
        }
    
        public function turnOff()
        {
            return 'I am quiet and peaceful shadow.';
        }
    }
    
                  
  • TurnOffCommand.php
                  
    <?php
    
    namespace DesignPatterns\Behavioral\Command;
    
    class TurnOffCommand implements CommandInterface
    {
        /**
         * @var Lamp
         */
        protected $lamp;
    
        /**
         * @param Lamp $lamp
         */
        public function __construct(Lamp $lamp)
        {
            $this->lamp = $lamp;
        }
    
        public function execute()
        {
            return $this->lamp->turnOff();
        }
    }
    
                  
  • TurnOnCommand.php
                  
    <?php
    
    namespace DesignPatterns\Behavioral\Command;
    
    class TurnOnCommand implements CommandInterface
    {
        /**
         * @var Lamp
         */
        protected $lamp;
    
        /**
         * @param Lamp $lamp
         */
        public function __construct(Lamp $lamp)
        {
            $this->lamp = $lamp;
        }
    
        public function execute()
        {
            return $this->lamp->turnOn();
        }
    }
    
                  
  • Test case:

    CommandTest.php
      
    <?php
    
    namespace DesignPatterns\Tests\Behavioral\Command;
    
    use DesignPatterns\Behavioral\Command\CommandRegistry;
    use DesignPatterns\Behavioral\Command\Lamp;
    use DesignPatterns\Behavioral\Command\TurnOffCommand;
    use DesignPatterns\Behavioral\Command\TurnOnCommand;
    use PHPUnit_Framework_TestCase;
    
    class CommandTest extends PHPUnit_Framework_TestCase
    {
        /**
         * @var CommandRegistry
         */
        protected static $registry;
    
        /**
         * @var Lamp
         */
        protected static $lamp;
    
        public static function setUpBeforeClass(): void
        {
            self::$registry = new CommandRegistry();
            self::$lamp = new Lamp();
        }
    
        public function testAddCommandToRegistry()
        {
            self::$registry->add(new TurnOnCommand(self::$lamp), 'ON');
            self::$registry->add(new TurnOffCommand(self::$lamp), 'OFF');
    
            $this->assertEquals(2, self::$registry->count());
        }
    
        public function testTurnOnCommand()
        {
            self::$registry->add(new TurnOnCommand(self::$lamp), 'ON');
            $this->assertEquals(self::$lamp->turnOn(), self::$registry->get('ON')->execute());
        }
    
        public function testTurnOffCommand()
        {
            self::$registry->add(new TurnOffCommand(self::$lamp), 'OFF');
            $this->assertEquals(self::$lamp->turnOff(), self::$registry->get('OFF')->execute());
        }
    }