Паттерн Состояние позволяет объекту менять поведение при смене внутреннего состояния. Вместо строки status, проверяемой в каждом методе, каждое состояние становится классом с поведением этого состояния, а объект делегирует текущему объекту-состоянию. Это объектная форма конечного автомата.

Начните с диаграммы

Состояния заказа `New`, `Paid`, `Shipped`, `Cancelled` и события между ними
Состояния заказа New, Paid, Shipped, Cancelled и события между ними

Заказ бывает New, затем Paid, затем Shipped; до отправки его можно отменить. Shipped и Cancelled — конечные: из них не выходит ни одно событие. Диаграмма перечисляет все состояния, допустимые события и переходы; всё нерисованное недопустимо.

Строка статуса

Первая версия хранит status и проверяет его в каждом методе. Это работает, но новое состояние затрагивает все методы, а правила переходов размазаны по if и строкам (опечатка вроде "shiped" — тихая ошибка).

python
class Order:
    def __init__(self):
        self.status = "new"

    def pay(self):
        if self.status != "new":
            raise ValueError(f"cannot pay in state {self.status}")
        self.status = "paid"

    def ship(self):
        if self.status != "paid":
            raise ValueError(f"cannot ship in state {self.status}")
        self.status = "shipped"

    def cancel(self):
        if self.status in ("shipped", "cancelled"):
            raise ValueError(f"cannot cancel in state {self.status}")
        self.status = "cancelled"