Behavioral PatternsState PatternMedium⏱️ ~3 min

Applying State Pattern to a Vending Machine

Domain: Vending Machine

A vending machine has four states: Idle (waiting for money), HasMoney (money inserted), Dispensing (delivering product), and OutOfStock. Each state handles user actions differently.

Class Design

«interface»
VendingMachineState
+ insertMoney(amount): void
+ selectProduct(id): void
+ dispense(): void
+ cancel(): void
IdleState
+ insertMoney()
+ selectProduct()
+ dispense()
+ cancel()
HasMoneyState
+ insertMoney()
+ selectProduct()
+ dispense()
+ cancel()
DispensingState
+ insertMoney()
+ selectProduct()
+ dispense()
+ cancel()
OutOfStockState
+ insertMoney()
+ selectProduct()
+ dispense()
+ cancel()
VendingMachine
- currentState: State
- inventory: Map
- balance: Money
+ setState(state): void
+ insertMoney(amt): void
+ selectProduct(id): void
+ dispense(): void
+ cancel(): void

State-Specific Behavior

IdleState:

  • insertMoney(): Accept money, transition to HasMoneyState
  • selectProduct(): Reject (no money inserted yet)
  • dispense(): Reject (invalid operation)
  • cancel(): Do nothing (no transaction active)

HasMoneyState:

  • insertMoney(): Add to balance, stay in HasMoneyState
  • selectProduct(): Validate product and price, transition to DispensingState if valid, but if insufficient funds or out of stock, display error and stay in HasMoneyState
  • dispense(): Reject (product not selected yet)
  • cancel(): Refund money, transition to IdleState

DispensingState:

  • insertMoney(): Reject (dispensing in progress)
  • selectProduct(): Reject (already dispensing)
  • dispense(): Deliver product, update inventory, check if any stock remains (if yes, transition to IdleState, but if no stock, transition to OutOfStockState)
  • cancel(): Reject (too late to cancel)

OutOfStockState:

  • All operations: Reject with "Out of Stock" message
  • Special: restock() method transitions back to IdleState

State Transition Example

// In HasMoneyState.selectProduct()
if (product exists AND balance >= price AND inStock) {
  context.setState(new DispensingState())
} else if (NOT inStock) {
  context.refund()
  context.setState(new OutOfStockState())
} else {
  display "Insufficient funds"
  // Stay in HasMoneyState
}
Interview Tip: In machine coding rounds, interviewers look for how you handle invalid state transitions (like canceling during dispensing). Each state should explicitly handle or reject every possible operation.
💡 Key Takeaways
Each state implements all operations but behaves differently
States trigger transitions based on business logic (inventory, balance)
Invalid operations in a state are explicitly rejected, not ignored
Vending machine context holds inventory and balance data
State transitions handle edge cases like out of stock during purchase
📌 Examples
1Idle to HasMoney when money inserted
2HasMoney to Dispensing when valid product selected
3Dispensing to OutOfStock if last item sold
4HasMoney to Idle when cancel requested
← Back to State Pattern Overview
Applying State Pattern to a Vending Machine | State Pattern - System Overflow