Что такое паттерн Команда (Command) и как он применяется?

Ответ

Паттерн Команда (Command) — это поведенческий паттерн проектирования, который инкапсулирует запрос в виде объекта. Это позволяет параметризовать клиентов с различными запросами, ставить запросы в очередь или поддерживать отмену операций.

Основные компоненты:

  • Command (Интерфейс команды): Объявляет метод выполнения (например, execute()).
  • ConcreteCommand (Конкретная команда): Реализует интерфейс, связывая действие с получателем.
  • Invoker (Инициатор): Инициирует выполнение команды.
  • Receiver (Получатель): Объект, который знает, как выполнить само действие.

Пример на Java:

// Command
interface Command {
    void execute();
}

// ConcreteCommand
class LightOnCommand implements Command {
    private Light light; // Receiver
    public LightOnCommand(Light light) { this.light = light; }
    @Override
    public void execute() { light.turnOn(); }
}

// Invoker
class RemoteControl {
    private Command command;
    public void setCommand(Command command) { this.command = command; }
    public void pressButton() { command.execute(); }
}

// Receiver
class Light {
    public void turnOn() { System.out.println("Light is ON"); }
}

Применение и преимущества:

  • Отмена и повтор операций (Undo/Redo): Команда может хранить состояние для отката.
  • Очереди и планирование задач: Команды можно ставить в очередь или выполнять в разное время.
  • Макрокоманды: Создание составных команд из нескольких простых.
  • Слабосвязанная архитектура: Инициатор не зависит от конкретных операций получателя.

Ответ 18+ 🔞

А, паттерн Команда, ёпта! Это ж как раз про то, когда ты хочешь сказать "сделай что-нибудь", но не орешь прямо в ухо исполнителю, а пишешь ему аккуратную записочку. Красота, блядь!

Смотри, в чём суть, а то сейчас мозг набекрень поставит. Вместо того чтобы напрямую дёргать методы какого-нибудь объекта (получателя, Receiver), ты это своё желание — «включи свет», «закажи пиццу» — заворачиваешь в отдельную обёртку, в объект-команду. И этот объект уже знает, кого и как надо еб... то есть, выполнить.

Кто тут кто, блядь:

  • Команда (Command) — это типа интерфейс, бумажка с печатью, на которой написано одно слово: execute(). Всё. Что делать — не указано, просто «исполни».
  • Конкретная команда (ConcreteCommand) — это уже заполненный бланк. «Гражданин Лампочка (Light), включись нахуй!». Этот бланк знает и про получателя, и про конкретный метод, который надо вызвать.
  • Инициатор (Invoker) — это тот, у кого чешутся руки нажать кнопку. У него есть эта самая команда-бумажка, и он, не вникая в детали, просто говорит: «Жми!» (pressButton()). Ему похуй, что там внутри — свет включится или чайник вскипит.
  • Получатель (Receiver) — это, собственно, тот, кто в итоге всё и делает. Лампочка, которая умеет turnOn(). Единственный, у кого есть реальные знания и сила, блядь.

Вот смотри, как это в коде выглядит, сука:

// Command - та самая пустая бумажка с печатью
interface Command {
    void execute(); // Всё, что она говорит: "Сделай!"
}

// ConcreteCommand - заполненный ордер на включение света
class LightOnCommand implements Command {
    private Light light; // Ага, получатель - это свет (Receiver)
    public LightOnCommand(Light light) { this.light = light; }
    @Override
    public void execute() { light.turnOn(); } // Конкретный приказ: "Включись!"
}

// Invoker - пульт, у которого одна кнопка и он не парится
class RemoteControl {
    private Command command; // Держит он эту бумажку-команду
    public void setCommand(Command command) { this.command = command; }
    public void pressButton() { command.execute(); } // Нажал - и совесть чиста!
}

// Receiver - лампочка, которая реально умеет гореть
class Light {
    public void turnOn() { System.out.println("Light is ON"); } // Вот она, магия!
}

И зачем этот цирк, спросишь? А я тебе скажу, зачем, блядь:

  • Отмена/Повтор (Undo/Redo): Это же охуенно! Раз команда — это объект, она может помнить, как было ДО. Нажал «вкл» — команда выполнилась. Захотел отменить — пожалуйста, у команды может быть метод undo(), который скажет лампочке turnOff(). Всё, ебушки-воробушки, состояние вернулось!
  • Очереди и отложенный запуск: Команды можно, блядь, в список сложить и выполнить потом, когда вздумается. Или отправить по сети на другой конец света. Пульт (Invoker) даже не узнает, что его приказ выполнили через час на другом сервере.
  • Макрокоманды: Это когда из кучи мелких «запросочек» делаешь одну здоровенную «командищу», которая делает всё и сразу. Нажал одну кнопку — и свет выключился, музыка встала на паузу, а кофе начал греться. Удобно, сука!
  • Слабые связи, ёпта: Самый сок. Пульту (инициатору) вообще похуй, что там за устройство. Дашь ему команду «включи гирлянду» — он нажмёт. Дашь команду «запусти двигатель» — он тоже нажмёт. Он знает только про интерфейс Command. А что там внутри execute() происходит — это твои личные проблемы, получатель.

Короче, паттерн Команда — это как нанять личного адъютанта. Ты ему (инициатору) говоришь: «Сделай вот это!» (отдаешь команду-объект). А он уже сам разбирается, кого позвать (получателя) и как именно ему объяснить задачу. Красота, блядь, а не паттерн!