← Назад к вопросам

В чем разница между паттернами стратегия и команда?

3.0 Senior🔥 251 комментариев
#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между паттернами Strategy и Command

Strategy и Command — это два поведенческих паттерна проектирования, которые часто путают. Хотя они имеют сходные структуры, их назначение и контекст использования существенно отличаются.

Strategy (Стратегия)

Pattern Strategy предназначен для выбора одного из нескольких алгоритмов для решения одной задачи. Выбор стратегии происходит во время выполнения программы.

// Интерфейс стратегии
public interface PaymentStrategy {
    void pay(double amount);
}

// Конкретные стратегии
public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    
    public CreditCardPayment(String cardNumber) {
        this.cardNumber = cardNumber;
    }
    
    @Override
    public void pay(double amount) {
        System.out.println("Оплачено " + amount + " руб. с карты: " + cardNumber);
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String email;
    
    public PayPalPayment(String email) {
        this.email = email;
    }
    
    @Override
    public void pay(double amount) {
        System.out.println("Оплачено " + amount + " руб. через PayPal: " + email);
    }
}

public class BitcoinPayment implements PaymentStrategy {
    private String walletAddress;
    
    public BitcoinPayment(String walletAddress) {
        this.walletAddress = walletAddress;
    }
    
    @Override
    public void pay(double amount) {
        System.out.println("Оплачено " + amount + " руб. в Bitcoin: " + walletAddress);
    }
}

// Контекст
public class Order {
    private double total;
    private PaymentStrategy strategy;
    
    public Order(double total) {
        this.total = total;
    }
    
    // Выбираем стратегию во время выполнения
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void checkout() {
        if (strategy == null) {
            throw new IllegalStateException("Payment strategy not set");
        }
        strategy.pay(total);
    }
    
    public static void main(String[] args) {
        Order order = new Order(1000);
        
        // Динамический выбор стратегии
        order.setPaymentStrategy(new CreditCardPayment("1234-5678-9012"));
        order.checkout(); // Платёж с карты
        
        order.setPaymentStrategy(new PayPalPayment("user@example.com"));
        order.checkout(); // Платёж через PayPal
    }
}

Command (Команда)

Pattern Command инкапсулирует запрос как объект, позволяя параметризовать клиентов с разными запросами, ставить запросы в очередь, логировать запросы и поддерживать отмену операций.

// Интерфейс команды
public interface Command {
    void execute();
    void undo();
}

// Receiver — объект, который выполняет действие
public class Light {
    private boolean isOn = false;
    
    public void turnOn() {
        isOn = true;
        System.out.println("Свет включён");
    }
    
    public void turnOff() {
        isOn = false;
        System.out.println("Свет выключен");
    }
}

// Конкретные команды
public class TurnOnCommand implements Command {
    private Light light;
    
    public TurnOnCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.turnOn();
    }
    
    @Override
    public void undo() {
        light.turnOff();
    }
}

public class TurnOffCommand implements Command {
    private Light light;
    
    public TurnOffCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.turnOff();
    }
    
    @Override
    public void undo() {
        light.turnOn();
    }
}

// Invoker — отправитель команд
public class RemoteControl {
    private Stack<Command> history = new Stack<>();
    
    public void pressButton(Command command) {
        command.execute();
        history.push(command);
    }
    
    public void pressUndo() {
        if (!history.isEmpty()) {
            Command command = history.pop();
            command.undo();
        }
    }
    
    public static void main(String[] args) {
        Light light = new Light();
        RemoteControl remote = new RemoteControl();
        
        remote.pressButton(new TurnOnCommand(light));
        remote.pressButton(new TurnOffCommand(light));
        remote.pressButton(new TurnOnCommand(light));
        
        remote.pressUndo(); // Отмена последней команды
        remote.pressUndo();
    }
}

Ключевые отличия

АспектStrategyCommand
ЦельВыбор алгоритма для решения задачиИнкапсуляция запроса как объекта
ИспользованиеЕсли есть несколько способов сделать одно и то жеДля отделения отправителя от получателя
ИсторияНе сохраняется, текущая стратегияСохраняется, можно откатывать
ПараметрыStrategy выбирается один разCommands могут ставиться в очередь
ОтменаНе поддерживаетсяПоддерживается (undo/redo)
СвязьТесно связана с контекстомСлабо связана (отправитель не знает о получателе)

Когда использовать

Strategy используйте, когда:

  • Нужно выбрать один из нескольких алгоритмов
  • Выбор делается во время выполнения
  • Нужна гибкость в выборе реализации (например, разные способы оплаты)

Command используйте, когда:

  • Нужно ставить операции в очередь
  • Нужна функция отмены/повтора
  • Нужно логировать или записывать команды
  • Нужно отделить отправителя от получателя

Практический пример из реальной жизни

В игре стратегия выбирает, как врагом двигаться (агрессивно, осторожно, защищаться), а команда — это конкретное действие (атаковать, прыгнуть, повернуться), которое можно отменить через undo.