В чем разница между паттернами стратегия и команда?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между паттернами 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();
}
}
Ключевые отличия
| Аспект | Strategy | Command |
|---|---|---|
| Цель | Выбор алгоритма для решения задачи | Инкапсуляция запроса как объекта |
| Использование | Если есть несколько способов сделать одно и то же | Для отделения отправителя от получателя |
| История | Не сохраняется, текущая стратегия | Сохраняется, можно откатывать |
| Параметры | Strategy выбирается один раз | Commands могут ставиться в очередь |
| Отмена | Не поддерживается | Поддерживается (undo/redo) |
| Связь | Тесно связана с контекстом | Слабо связана (отправитель не знает о получателе) |
Когда использовать
Strategy используйте, когда:
- Нужно выбрать один из нескольких алгоритмов
- Выбор делается во время выполнения
- Нужна гибкость в выборе реализации (например, разные способы оплаты)
Command используйте, когда:
- Нужно ставить операции в очередь
- Нужна функция отмены/повтора
- Нужно логировать или записывать команды
- Нужно отделить отправителя от получателя
Практический пример из реальной жизни
В игре стратегия выбирает, как врагом двигаться (агрессивно, осторожно, защищаться), а команда — это конкретное действие (атаковать, прыгнуть, повернуться), которое можно отменить через undo.