← Назад к вопросам

Что такое State machine?

2.0 Middle🔥 61 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

State Machine (Конечный автомат)

State Machine (FSM — Finite State Machine) — это абстрактная вычислительная модель, которая описывает систему, имеющую конечное число состояний. В каждый момент времени система находится в одном из этих состояний и может переходить в другие состояния на основе определённых условий (событий).

Главная идея: вместо сложной логики с множеством if-else условий, мы явно определяем состояния и переходы между ними.

Ключевые компоненты

  1. Состояния (States) — возможные условия системы
  2. События (Events) — триггеры для переходов
  3. Переходы (Transitions) — правила смены состояний на основе событий
  4. Начальное состояние (Initial State) — первоначальное состояние
  5. Конечные состояния (Terminal States) — состояния, в которых система может завершиться

Простой пример: Заказ в интернет-магазине

Состояния: Создан → Оплачен → Отправлен → Доставлен → Завершён

События:
- Создан → Оплачен (событие: оплата прошла)
- Оплачен → Отправлен (событие: товар в пути)
- Отправлен → Доставлен (событие: товар доставлен)
- Доставлен → Завершён (событие: покупатель принял товар)

Реализация на Python

Вариант 1: Простая реализация на классах

from enum import Enum
from typing import Optional

class OrderState(Enum):
    CREATED = "created"
    PAID = "paid"
    SHIPPED = "shipped"
    DELIVERED = "delivered"
    COMPLETED = "completed"

class Order:
    def __init__(self, order_id: str):
        self.order_id = order_id
        self.state = OrderState.CREATED
    
    def pay(self) -> bool:
        """Попытка перейти в состояние PAID"""
        if self.state == OrderState.CREATED:
            self.state = OrderState.PAID
            return True
        return False
    
    def ship(self) -> bool:
        """Попытка перейти в состояние SHIPPED"""
        if self.state == OrderState.PAID:
            self.state = OrderState.SHIPPED
            return True
        return False
    
    def deliver(self) -> bool:
        """Попытка перейти в состояние DELIVERED"""
        if self.state == OrderState.SHIPPED:
            self.state = OrderState.DELIVERED
            return True
        return False
    
    def complete(self) -> bool:
        """Попытка перейти в состояние COMPLETED"""
        if self.state == OrderState.DELIVERED:
            self.state = OrderState.COMPLETED
            return True
        return False

# Использование
order = Order("order-123")
print(order.state)  # OrderState.CREATED
order.pay()
print(order.state)  # OrderState.PAID
order.ship()
print(order.state)  # OrderState.SHIPPED

Вариант 2: Более гибкая реализация с переходами

from dataclasses import dataclass
from enum import Enum
from typing import Dict, Callable, Optional

class State(Enum):
    IDLE = "idle"
    RUNNING = "running"
    PAUSED = "paused"
    STOPPED = "stopped"

class Event(Enum):
    START = "start"
    PAUSE = "pause"
    RESUME = "resume"
    STOP = "stop"

class StateMachine:
    def __init__(self, initial_state: State):
        self.current_state = initial_state
        self.transitions: Dict[State, Dict[Event, State]] = {}
        self.on_enter_callbacks: Dict[State, Callable] = {}
        self.on_exit_callbacks: Dict[State, Callable] = {}
    
    def add_transition(self, from_state: State, event: Event, to_state: State):
        """Добавить переход между состояниями"""
        if from_state not in self.transitions:
            self.transitions[from_state] = {}
        self.transitions[from_state][event] = to_state
    
    def on_enter(self, state: State):
        """Декоратор для обработчика входа в состояние"""
        def decorator(func: Callable):
            self.on_enter_callbacks[state] = func
            return func
        return decorator
    
    def on_exit(self, state: State):
        """Декоратор для обработчика выхода из состояния"""
        def decorator(func: Callable):
            self.on_exit_callbacks[state] = func
            return func
        return decorator
    
    def trigger(self, event: Event) -> bool:
        """Триггер события для перехода"""
        if self.current_state not in self.transitions:
            return False
        
        next_state = self.transitions[self.current_state].get(event)
        if next_state is None:
            return False
        
        # Вызвать callback выхода
        if self.current_state in self.on_exit_callbacks:
            self.on_exit_callbacks[self.current_state]()
        
        # Изменить состояние
        self.current_state = next_state
        
        # Вызвать callback входа
        if self.current_state in self.on_enter_callbacks:
            self.on_enter_callbacks[self.current_state]()
        
        return True

# Использование
fsm = StateMachine(State.IDLE)
fsm.add_transition(State.IDLE, Event.START, State.RUNNING)
fsm.add_transition(State.RUNNING, Event.PAUSE, State.PAUSED)
fsm.add_transition(State.PAUSED, Event.RESUME, State.RUNNING)
fsm.add_transition(State.RUNNING, Event.STOP, State.STOPPED)
fsm.add_transition(State.PAUSED, Event.STOP, State.STOPPED)

@fsm.on_enter(State.RUNNING)
def on_start():
    print("Система запущена")

@fsm.on_exit(State.RUNNING)
def on_stop():
    print("Система остановлена")

print(fsm.current_state)  # State.IDLE
fsm.trigger(Event.START)
print(fsm.current_state)  # State.RUNNING
fsm.trigger(Event.PAUSE)
print(fsm.current_state)  # State.PAUSED

Использование библиотеки transitions

Для больших проектов используют готовую библиотеку:

pip install transitions
from transitions import Machine

states = ["solid", "liquid", "gas"]
transitions = [
    {"trigger": "melt", "source": "solid", "dest": "liquid"},
    {"trigger": "evaporate", "source": "liquid", "dest": "gas"},
    {"trigger": "sublimate", "source": "solid", "dest": "gas"},
    {"trigger": "ionize", "source": "gas", "dest": "plasma"},
]

class Matter:
    pass

matter = Matter()
machine = Machine(model=matter, states=states, transitions=transitions, initial="solid")

print(matter.state)  # solid
matter.melt()
print(matter.state)  # liquid
matter.evaporate()
print(matter.state)  # gas

Преимущества State Machine

  1. Ясность логики — явное определение состояний и переходов
  2. Предотвращение ошибок — невозможны недопустимые переходы
  3. Масштабируемость — легко добавлять новые состояния
  4. Тестируемость — каждый переход можно тестировать отдельно
  5. Визуализация — легко нарисовать диаграмму состояний

Когда использовать

  • Обработка заказов
  • Управление рабочими процессами (workflow)
  • Сценарии в играх
  • Управление формами и навигацией
  • Протоколы коммуникации
  • Управление жизненным циклом объектов

State Machine — это мощный паттерн для моделирования сложной логики в виде простых и понятных переходов между состояниями.