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

Order states New, Paid, Shipped, Cancelled and the events between them
Order states New, Paid, Shipped, Cancelled and the events between them

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).

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"