Паттерн Состояние позволяет объекту менять поведение при смене внутреннего состояния. Вместо строки status, проверяемой в каждом методе, каждое состояние становится классом с поведением этого состояния, а объект делегирует текущему объекту-состоянию. Это объектная форма конечного автомата.
Начните с диаграммы
New, Paid, Shipped, Cancelled и события между нимиЗаказ бывает New, затем Paid, затем Shipped; до отправки его можно отменить. Shipped и Cancelled — конечные: из них не выходит ни одно событие. Диаграмма перечисляет все состояния, допустимые события и переходы; всё нерисованное недопустимо.
Строка статуса
Первая версия хранит status и проверяет его в каждом методе. Это работает, но новое состояние затрагивает все методы, а правила переходов размазаны по if и строкам (опечатка вроде "shiped" — тихая ошибка).
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"