Skip to content
Jarviix
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.

Related reads