The State pattern lets an object change its behavior when its internal state changes. Instead of a status string checked in every method, each state becomes a class holding the behavior of that state, and the object delegates to its current state object. It is the object-oriented form of a finite state machine.
Start with a diagram
An order is New, then Paid, then Shipped; it can be cancelled before shipping. Shipped and Cancelled are final: no event leaves them. The diagram lists every state, every legal event and every transition; whatever is not drawn is illegal.
The status string
The first version stores status and checks it in every method. It works, but a new state touches all methods, and the rules of transitions are spread over ifs and strings (a typo like "shiped" is a silent bug).
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"