The State pattern lets an object change its behavior when its internal state changes. Instead of using many if
or switch
statements, the pattern helps you organize state-specific behavior into separate classes.
In many programs, an object’s behavior depends on its current state. For example, a button may behave differently when pressed, hovered, or disabled. If you manage these behaviors using conditionals spread throughout your code, it can become hard to understand and update. The State pattern solves this by letting each state be handled by its own class, keeping logic organized and easier to modify.
Use this pattern when:
if
/else
or switch
statements.Avoid this pattern if:
enum
or basic conditionals might be easier.The pattern has three main components:
handle()
) that all concrete states must implement.Imagine ordering food at a restaurant. If you order a burger, you get a burger; if you order a salad, you get a salad. Each order represents a state, and the waiter delivers a different result depending on what you asked for. The waiter (context) changes behavior based on your order (state).
Here’s a basic example in Python:
class Context:
def __init__(self, state):
self._state = state
self._state.set_context(self)
def transition_to(self, state):
print("Context: Transitioning to", type(state).__name__)
self._state = state
self._state.set_context(self)
def request(self):
self._state.handle()
class State:
def set_context(self, context):
self._context = context
def handle(self):
pass
class ConcreteStateA(State):
def handle(self):
print("ConcreteStateA handles request")
self._context.transition_to(ConcreteStateB())
class ConcreteStateB(State):
def handle(self):
print("ConcreteStateB handles request")
self._context.transition_to(ConcreteStateA())
context = Context(ConcreteStateA())
context.request() # ConcreteStateA handles request
context.request() # ConcreteStateB handles request
Here, the context starts in ConcreteStateA
, handles a request, and transitions to ConcreteStateB
, which then transitions back on the next request. Each state is responsible for its own behavior and any transitions.
For a complete implementation in Python, visit: State Pattern on GitHub