🧠 State ≠ State Machine: разбираем поведенческий паттерн, который часто путают
Хотел написать короткий пост о своём любимом паттерне проектирования. Но пока разбирался — понял, что знаю о нём гораздо меньше, чем думал 😅. В итоге короткий пост превратился в полноценный лонгрид с примерами. Буду публиковать его по кусочкам. Рассказываю, что такое паттерн State, когда его использовать, как не перепутать его с State Machine. 👇
State паттерн ("Состояние") — это поведенческий паттерн проектирования, который позволяет объекту изменять своё поведение в зависимости от внутреннего состояния. Многие описывают этот паттерн в контексте паттерна State Machine ("Конечный автомат", "Машина состояний") и не рассматривают в отрыве от этой концепции. На самом деле State самостоятельный паттерн и часто используется независимо.
📌 Когда использовать State
Паттерн State особенно полезен когда:
- Логика поведения объекта зависит от его различных состояний.
- Логика содержит множество условных операторов (if/else, switch), зависящих от текущего состояния или внутренних флагов.
- Хотим убрать связь между состоянием и поведением.
- Есть множество состояний и они могут меняться со временем.
Примеры:
- Текстовый редактор с режимами: чтение, редактирование, навигация.
- Состояния заказа / платежа.
- Жизненный цикл кредита/займа.
- Транзакции между счетами.
- Активность пользовательского аккаунта.
✅ Преимущества, которые мы получим, когда используем State:
- Более чистый и структурированный код - за счет применения Single Responsibility и Open-Closed принципов ООП.
- Уменьшаем связанность между компонентами.
- Расширяемость - добавление нового состояния требует минимального изменения существующих.
- Инкапсуляция логики.
✍ Пример реализации на Java
Есть несколько вариантов реализации паттерна State, один из них нарушает Liskov Substitution Principle, но тем не менее он представлен на множестве ресурсов. Рассмотрим сначала более правильный вариант:
1. Определяем интерфейс состояния:
2. Конкретные состояния реализуют интерфейс `EditorState`:
3. Контекст, который хранит текущее состояние:
Тестирование:
Результат:
А теперь реализация с нарушением LSP принципа. Иногда приходится использовать такое решение, исходя из потребностей системы и бизнес логики:
📌 Вывод
Паттерн State — подходящий инструмент для управления состоянием объектов и организации чистого кода. Его стоит использовать, когда требуется более сложная система управления состояниями с поддержкой переходов, валидации и визуализации. Он полезен, когда поведение объекта сложно и зависит от множества состояний. Однако если нужно явно описывать все возможные переходы между состояниями и валидировать их, стоит посмотреть в сторону паттерна State Machine.
Использовали паттерн? Потом через полгода открывая проект, говорили: "Да откуда же это взялось???"
Подпишись на мой канал в telegram