Питання 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]] — перебір станів
  • [[2. Які категорії патернів існують]] — Behavioral патерни
  • [[16. Які антипатерни ви знаєте]] — Sequential Coupling
  • [[1. Що таке патерни проектування]] — Behavioral категорія