Команда

Аналогія

Ви прийшли до ресторану. Ви (Client) просите офіціанта (Invoker) принести блюда (Command). Офіціант перенаправляє запит шеф-кухареві (Receiver), який знає, що і як готувати. Інший приклад: ви (Client) включаєте (Command) телевізор (Receiver) за допомогою пульта (Invoker).

Стисло

Шаблон “Команда” дозволяє інкапсулювати дії в об’єкти. Ключова ідея – надати кошти відділення клієнта від отримувача.

Вікіпедія

У шаблоні «Команда» об’єкт використовується для інкапсуляції всієї інформації, яка потрібна на виконання дії чи його ініціювання пізніше. Інформація включає ім’я методу; об’єкт, який володіє способом; значення параметрів методу

Приклад

Спочатку зробимо одержувача, що містить реалізації кожної дії, яка може бути виконана.

// Receiver
class Bulb
{
    public function turnOn()
    {
        echo "Bulb has been lit";
    }

    public function turnOff()
    {
        echo "Darkness!";
    }
}

Тепер зробимо інтерфейс, який реалізовуватиме кожна команда. Також зробимо набір команд.

interface Command
{
    public function execute();
    public function undo();
    public function redo();
}

// Command
class TurnOn implements Command
{
    protected $bulb;

    public function __construct(Bulb $bulb)
    {
        $this->bulb = $bulb;
    }

    public function execute()
    {
        $this->bulb->turnOn();
    }

    public function undo()
    {
        $this->bulb->turnOff();
    }

    public function redo()
    {
        $this->execute();
    }
}

class TurnOff implements Command
{
    protected $bulb;

    public function __construct(Bulb $bulb)
    {
        $this->bulb = $bulb;
    }

    public function execute()
    {
        $this->bulb->turnOff();
    }

    public function undo()
    {
        $this->bulb->turnOn();
    }

    public function redo()
    {
        $this->execute();
    }
}

Тепер зробимо викликаючого Invoker, з яким взаємодіятиме клієнт для обробки команд.

// Invoker
class RemoteControl
{
    public function submit(Command $command)
    {
        $command->execute();
    }
}

Подивимося, як це може використовувати клієнт:

$ bulb = New Bulb ();

$turnOn = New TurnOn($bulb);
$turnOff = New TurnOff($bulb);

$ remote = new RemoteControl();
$remote->submit($turnOn); // Лампочка спалахнула!
$remote->submit($turnOff); // Темрява!

Шаблон “Команда” можна використовувати і для реалізації системи на основі транзакцій. Тобто системи, де ви зберігаєте історію команд у міру їх виконання. Якщо остання команда виконана успішно, все добре. Інакше система ітерує з історії та робить undo для всіх виконаних команд.

Залишити коментар