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