Skip to content
BytePatterns

State Pattern

Low-Level Design: lesson 9 of 10

Same method call, different answer, because the object moved on.

Lesson 9 of 10 · 5 min

State Pattern

Step 1 of 12

Some objects answer the same call differently because they have moved on.

The Idea

Some objects answer the same call differently depending on where they are in their life. Model that explicitly: name the states, list which actions each one allows, and let the state decide what comes next. Illegal actions bounce, leaving the object untouched.

Real-World Example

A passport application. Freshly submitted, you can amend the address; once it has gone to print, the same request is simply refused and you start again. The counter clerk is not being difficult — the stage decides the menu.

The Code

class Application:
    ALLOWED = {"draft": ["submit"], "submitted": ["check"],
               "checked": ["print"], "printed": []}
    NEXT = {"submit": "submitted", "check": "checked", "print": "printed"}
    def __init__(self): self.state = "draft"
    def do(self, action):
        if action not in self.ALLOWED[self.state]:      # the state owns the menu
            return action + " refused while " + self.state
        self.state = self.NEXT[action]
        return "now " + self.state

a = Application()
print(a.do("submit"))     # now submitted
print(a.do("print"))      # print refused while submitted
print(a.do("check"))      # now checked

Your turn

Put the steps in the right order.

  1. The state changes, and later actions are judged by the new rules
  2. An action request arrives at the object
  3. The object asks its current state whether that action is allowed
  4. A legal action runs; an illegal one is refused with no side effects

Mini quiz

1 / 3

State pattern replaces: