Вопрос 13 · Раздел 2

В чём разница между State и Strategy?

Оба паттерна похожи, но цель у них разная:

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

Оба паттерна похожи, но цель у них разная:

Strategy — выбор алгоритма извне (клиент решает):

// Клиент сам выбирает стратегию
order.setPaymentStrategy(new CreditCardPayment());  // Извне
order.pay();

State — изменение поведения изнутри (объект сам решает):

// Объект сам меняет состояние
order.process();  // Внутри: если оплачен → отправить, если нет → ждать

Простая аналогия:

  • Strategy: Вы выбираете маршрут в навигаторе (на машине/пешком)
  • State: Светофор сам меняет цвет (красный → жёлтый → зелёный)

🟡 Middle Level

Strategy: Внешнее управление

interface SortStrategy { void sort(List<Integer> list); }

class QuickSort implements SortStrategy { ... }
class MergeSort implements SortStrategy { ... }

// КЛИЕНТ решает
List<Integer> data = new ArrayList<>();
Sorter sorter = new Sorter();
sorter.setStrategy(new QuickSort());  // Клиент выбрал
sorter.sort(data);

State: Внутреннее управление

interface OrderState { void process(Order order); }

class Order {
    private OrderState state;
    void setState(OrderState s) { this.state = s; }
    void process() { state.process(this); } // делегирование состоянию
}

class NewState implements OrderState {
    public void process(Order order) {
        // Переход в следующее состояние
        // Прямое создание состояний (new PaidState()) — антипаттерн (tight coupling).
        // Правильный подход: transitions через Registry/Factory.
        order.setState(new PaidState());
    }
}

class PaidState implements OrderState {
    public void process(Order order) {
        order.setState(new ShippedState());
    }
}

// ОБЪЕКТ сам меняет состояние
Order order = new Order();
order.setState(new NewState());
order.process();  // Внутри: NewState → PaidState
order.process();  // Внутри: PaidState → ShippedState

Сравнение

Критерий Strategy State
Кто выбирает Клиент Сам объект
Когда меняется Runtime, по желанию При изменении состояния
Зависимость Стратегии не знают друг о друге Состояния знают о переходах
Цель Замена алгоритма Управление поведением

🔴 Senior Level

Architecture Intent

Strategy = Dependency Injection для алгоритмов
  → Внедряем нужный алгоритм
  → Алгоритмы независимы

State = Finite State Machine
  → Состояния связаны переходами
  → Каждое состояние знает о следующих

Coupling Differences

// Strategy: стратегии НЕ знают друг о друге
class CreditCardPayment implements PaymentStrategy { }
class PayPalPayment implements PaymentStrategy { }
// Нет зависимостей между ними

// State: состояния знают о переходах
class NewState implements OrderState {
    public void process(Order order) {
        order.setState(new PaidState());  // Знает о PaidState!
    }
}
// Связаны через контекст

Production Experience

Реальный сценарий:

  • Заказ: 5 состояний
  • Сначала использовали Strategy → клиент управлял переходами
  • Баги: заказ из “Доставлен” перешёл в “Новый”
  • Решение: State machine с валидацией переходов
  • Результат: невозможны невалидные переходы

Best Practices

  1. Strategy для замены алгоритмов
  2. State для управления жизненным циклом
  3. Enum для простых состояний
  4. Spring Statemachine для enterprise
  5. Валидация переходов в State

Резюме для Senior

  • Strategy = клиент выбирает алгоритм
  • State = объект управляет своим поведением
  • Strategy = независимые алгоритмы
  • State = связанные переходы между состояниями
  • State Machine предотвращает невалидные переходы

🎯 Шпаргалка для интервью

Обязательно знать:

  • Strategy — клиент выбирает алгоритм извне, State — объект меняет поведение изнутри
  • Strategy: алгоритмы независимы друг от друга, State: состояния связаны переходами
  • Strategy = Dependency Injection для алгоритмов, State = Finite State Machine
  • State предотвращает невалидные переходы (нельзя из “Доставлен” перейти в “Новый”)
  • Template Method — замена частей алгоритма через наследование, Strategy — весь алгоритм через композицию
  • Для простых состояний: Enum с абстрактными методами, для enterprise: Spring Statemachine
  • Прямое создание состояний (new PaidState()) — tight coupling, правильно: transitions через Registry/Factory

Частые уточняющие вопросы:

  • Когда использовать State вместо Strategy? — Когда есть жизненный цикл с валидными переходами (заказ, документ)
  • Почему состояния должны знать о переходах? — Иначе клиент может сделать невалидный переход
  • Чем Template Method отличается от Strategy? — Template Method = части алгоритма (наследование), Strategy = весь алгоритм (композиция)
  • Что делать если переходов очень много? — State machine с таблицей переходов, Spring Statemachine

Красные флаги (НЕ говорить):

  • “Strategy и State — это одно и то же” — принципиально разная цель и управление
  • “Клиент должен управлять состояниями” — тогда это Strategy, не State
  • “State machine — это overengineering” — при 5+ состояниях без него будут баги с переходами
  • “Состояния не должны знать друг о друге” — тогда невозможно валидировать переходы

Связанные темы:

  • [[10. Когда использовать Strategy]] — основной паттерн Strategy
  • [[15. Что такое Iterator pattern]] — перебор состояний
  • [[2. Какие категории паттернов существуют]] — Behavioral паттерны
  • [[16. Какие антипаттерны вы знаете]] — Sequential Coupling
  • [[1. Что такое паттерны проектирования]] — Behavioral категория