LLD7 min read
Vending Machine
A textbook state machine — Idle / HasMoney / Dispensing / Refunding.
lldstate-machineoop
Intro
A vending machine maintains an inventory of products and accepts coins/notes. It's the canonical example for the State pattern: behaviour for selectProduct, insertCoin and dispense changes depending on the current state.
Functional
- Show inventory; mark out-of-stock items.
- Accept multiple denominations; aggregate the inserted total.
- On product select + sufficient money, dispense and return change.
- On cancel, refund the inserted amount.
Non-functional
- Atomic dispense — never lose a sale or overcharge.
- Pluggable coin-change algorithm (bank with limited denominations vs. unlimited).
Components
Inventory
Stock per slot; thread-safe decrement on dispense.
CoinBank
Available denominations; computes change if possible.
VendingState
Interface: Idle, HasMoney, Dispensing, Refunding.
VendingMachine
Holds current state; delegates each action to it.
Code
Snippetjava
interface VendingState {
void insertCoin(VendingMachine m, int cents);
void selectProduct(VendingMachine m, String code);
void cancel(VendingMachine m);
}
class IdleState implements VendingState {
public void insertCoin(VendingMachine m, int c) { m.balance += c; m.setState(new HasMoneyState()); }
public void selectProduct(VendingMachine m, String code) { /* no-op */ }
public void cancel(VendingMachine m) { /* no-op */ }
}
class HasMoneyState implements VendingState {
public void insertCoin(VendingMachine m, int c) { m.balance += c; }
public void selectProduct(VendingMachine m, String code) {
Product p = m.inventory.peek(code);
if (p == null) return;
if (m.balance < p.price) return;
m.setState(new DispensingState(code));
}
public void cancel(VendingMachine m) { m.refund(); m.setState(new IdleState()); }
}Pitfalls
- Inventing 6 states when 3 suffice — start small, add only when behaviour diverges.
- Putting business logic outside the state class — defeats the pattern.