← Back to Design Patterns
🚦
Behavioral
State
Allows an object to change its behavior when its internal state changes — appears to change class.
The Problem
An object's behavior depends on its current state, leading to large if/else or switch statements scattered throughout methods that all check the current state.
How It Works
- ›Each state is a separate class that encapsulates behavior for that state
- ›State transitions happen by replacing the current state object
- ›Eliminates complex conditional logic scattered across methods
- ›New states can be added without modifying existing state classes (Open/Closed)
- ›Context delegates all state-dependent behavior to the current state object
When to Use
✓Object's behavior must change based on its state at runtime
✓Finite state machines: order lifecycle, connection states, player states
✓When state-specific code is duplicated across many conditional branches
✓When transitions between states need to be explicit and well-defined
Real-World Examples
🍎
iOS
UIViewController lifecycle (viewDidLoad → viewWillAppear → viewDidAppear), AVPlayer state
🤖
Android
Fragment backstack, MediaPlayer states (Idle→Initialized→Prepared→Started), ViewModel state flows
🌐
Web
Promise states (pending/fulfilled/rejected), XState FSM, React component lifecycle
Code Examples
Swift
protocol OrderState {
var label: String { get }
func next(order: Order)
}
class Order {
var state: OrderState = PendingState()
func advance() { state.next(order: self) }
func status() { print("Order: \(state.label)") }
}
class PendingState: OrderState {
var label = "Pending"
func next(order: Order) { order.state = ProcessingState() }
}
class ProcessingState: OrderState {
var label = "Processing"
func next(order: Order) { order.state = ShippedState() }
}
class ShippedState: OrderState {
var label = "Shipped"
func next(order: Order) { order.state = DeliveredState() }
}
class DeliveredState: OrderState {
var label = "Delivered"
func next(order: Order) { print("Already delivered") }
}
let order = Order()
order.status() // "Order: Pending"
order.advance(); order.status() // "Order: Processing"
order.advance(); order.status() // "Order: Shipped"
order.advance(); order.status() // "Order: Delivered"