Назад к вопросам
Middle
81
questionbank

Каковы отличия между шаблонами проектирования ООП 'Стратегия' и 'Состояние'?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Ключевое отличие в назначении и поведении:

  • Стратегия (Strategy): Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Позволяет клиенту независимо изменять алгоритм, который используется. Цель — выбор поведения объекта на основе выбранного алгоритма. Состояние объекта не является определяющим фактором для выбора стратегии.
  • Состояние (State): Позволяет объекту изменять своё поведение в зависимости от своего внутреннего состояния. На каждом шаге выполнения объект может иметь разное состояние, и на этом основе он меняет свою стратегию поведения. Цель — управление поведением объекта на основе его текущего состояния.

Сравнительная таблица:

Характеристика Стратегия (Strategy) Состояние (State)
Назначение Выбор алгоритма поведения. Изменение поведения объекта в зависимости от состояния.
Изменение Клиент явно выбирает и устанавливает стратегию. Объект сам переходит между состояниями, меняя поведение.
Отношения Слабая связь между контекстом и конкретной стратегией. Сильная связь между контекстом и состоянием.
Фокус Алгоритм, используемый объектом. Состояние объекта, которое определяет его поведение.
Переходы Переключение стратегии происходит явно. Переключение состояний происходит в ответ на события.
Пример Различные алгоритмы сортировки. Состояния светофора (красный, желтый, зеленый).
// Пример Стратегии
interface PaymentStrategy {
    void pay(int amount);
}

class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        // Логика оплаты кредитной картой
        System.out.println("Paid " + amount + " using Credit Card.");
    }
}

class PaypalPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        // Логика оплаты через PayPal
        System.out.println("Paid " + amount + " using Paypal.");
    }
}

class ShoppingCart {
    private PaymentStrategy paymentStrategy;

    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public void checkout(int amount) {
        if (this.paymentStrategy == null) {
             throw new IllegalStateException("Payment strategy not set!"); // Проверка на null
        }
        this.paymentStrategy.pay(amount);
    }
}
// Пример Состояния
interface VendingMachineState {
    void selectItem(VendingMachine machine);
    void insertMoney(VendingMachine machine);
    void dispenseItem(VendingMachine machine);
}

class NoMoneyState implements VendingMachineState {
    @Override
    public void selectItem(VendingMachine machine) {
        System.out.println("Please insert money first.");
    }

    @Override
    public void insertMoney(VendingMachine machine) {
        System.out.println("Money inserted. Moving to HasMoneyState.");
        machine.setState(new HasMoneyState());
    }

    @Override
    public void dispenseItem(VendingMachine machine) {
        System.out.println("Cannot dispense item, no money.");
    }
}

class HasMoneyState implements VendingMachineState {
    @Override
    public void selectItem(VendingMachine machine) {
        System.out.println("Item selected.");
        machine.setState(new ItemSelectedState()); // Переход в следующее состояние
    }

    @Override
    public void insertMoney(VendingMachine machine) {
        System.out.println("Money already inserted.");
    }

    @Override
    public void dispenseItem(VendingMachine machine) {
        System.out.println("Cannot dispense item, item not selected.");
    }
}

class ItemSelectedState implements VendingMachineState {
    @Override
    public void selectItem(VendingMachine machine) {
        System.out.println("Item already selected.");
    }

    @Override
    public void insertMoney(VendingMachine machine) {
        System.out.println("Money already inserted.");
    }

    @Override
    public void dispenseItem(VendingMachine machine) {
        System.out.println("Dispensing item.");
        machine.setState(new NoMoneyState()); // Возврат в начальное состояние
    }
}

class VendingMachine {
    private VendingMachineState currentState;

    public VendingMachine() {
        this.currentState = new NoMoneyState();
    }

    public void setState(VendingMachineState state) {
        this.currentState = state;
    }

    public void selectItem() {
        this.currentState.selectItem(this);
    }

    public void insertMoney() {
        this.currentState.insertMoney(this);
    }

    public void dispenseItem() {
        this.currentState.dispenseItem(this);
    }
}