# Design a Vending Machine — High-Level & Low-Level Design Interview Problems

Source: https://www.skillbyai.com/en/design-interviews/vending

> A state machine with money and inventory.

## States and transitions

Clarify: select product, insert coins or notes, dispense product and change, cancel for refund, restock by an operator. Model the machine as a **state machine**: `Idle` -> (insert money) -> `HasMoney` -> (select product with enough balance and stock) -> `Dispensing` -> `Idle`. Invalid actions in a state (selecting before paying, inserting while dispensing) are rejected by that state. Use the **State** pattern: a `VendingState` interface with `insertMoney`, `select` and `cancel`, and the `VendingMachine` context delegates to its current state. Track inventory per slot and handle change-making and "sold out" explicitly.

## State pattern sketch

Java; amounts in cents.

```java
interface VendingState {
    void insertMoney(VendingMachine m, int cents);
    void select(VendingMachine m, String slot);
    void cancel(VendingMachine m);
}

class IdleState implements VendingState {
    public void insertMoney(VendingMachine m, int cents) { m.addBalance(cents); m.setState(new HasMoneyState()); }
    public void select(VendingMachine m, String slot) { throw new IllegalStateException("Insert money first"); }
    public void cancel(VendingMachine m) { /* nothing to refund */ }
}

class HasMoneyState implements VendingState {
    public void insertMoney(VendingMachine m, int cents) { m.addBalance(cents); }
    public void select(VendingMachine m, String slot) {
        int price = m.priceOf(slot);
        if (!m.inStock(slot)) throw new IllegalStateException("Sold out");
        if (m.balance() < price) throw new IllegalStateException("Insufficient balance");
        m.dispense(slot);
        m.returnChange(m.balance() - price);
        m.resetBalance();
        m.setState(new IdleState());
    }
    public void cancel(VendingMachine m) { m.returnChange(m.balance()); m.resetBalance(); m.setState(new IdleState()); }
}
```

## A turnstile

A turnstile is locked until you pay, then unlocked until you pass. Each state accepts only the actions that make sense, which is exactly what the State pattern encodes.

**Quiz:** What should happen when a product is selected in the Idle state?

- [ ] The machine moves to Dispensing
- [ ] The product is dispensed for free
- [x] The request is rejected because no money has been inserted
- [ ] The balance becomes negative

*Answer:* The request is rejected because no money has been inserted. Each state allows only valid actions.
