В чем суть паттерна Command и каковы типичные сценарии его применения?

«В чем суть паттерна Command и каковы типичные сценарии его применения?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Паттерн Command инкапсулирует запрос в виде объекта, отделяя объект, инициирующий операцию (Invoker), от объекта, который знает, как ее выполнить (Receiver). Это позволяет параметризовать клиентов различными запросами, ставить их в очередь, логировать или поддерживать отмену операций (undo/redo).

Структура и пример:

// 1. Интерфейс команды
public interface Command {
    void execute();
    void undo(); // Для поддержки отмены
}

// 2. Конкретная команда
public class LightOnCommand implements Command {
    private Light light; // Receiver

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOn();
    }

    @Override
    public void undo() {
        light.turnOff();
    }
}

// 3. Invoker (например, кнопка в GUI)
public class Button {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void click() {
        command.execute();
    }
}

Типичные сценарии применения:

  • GUI и обработка действий: Кнопки, пункты меню.
  • Очереди и планировщики задач: Команды можно ставить в очередь на выполнение в другом потоке или в определенное время.
  • Транзакционные операции и отмена: Реализация многошаговых операций с возможностью отката.
  • Макрокоманды: Составные команды, выполняющие последовательность других команд.