Before you start
Elevator is a classic design problem that combines two module-3 patterns: State (idle/up/down) and Strategy (dispatch algorithm). Whether you use them BOTH, ONE, or NEITHER is the design decision.
The state question
An elevator has three phases: idle, moving up, moving
down. Each step() behaves differently:
- Idle → check requests, maybe pick a direction, maybe stay
- Moving up → move to next floor, maybe stop, maybe keep going
- Moving down → same, other direction
Full State pattern (one class per state) is one answer.
A simple _direction field plus branching in step()
is another. Both work. Argue your choice.
The strategy question
"How do we pick the next floor?" has multiple valid algorithms:
- SCAN (this lesson) — go all the way up, then all the way down
- LOOK — reverse as soon as there are no more requests in the current direction
- Nearest-car / SSTF — always go to the closest pending request
If you make dispatch a Strategy, swapping algorithms is one line. If you inline SCAN, adding LOOK later touches step(). Argue your choice — for MVP, either is defensible.
The rules discipline
Elevator has strong rules:
- Floor always in [0, N-1]. Never overshoot the bounds.
- Serving a floor clears requests. Both external calls (both directions) and internal selects for that floor.
- Idle → no motion. No requests, no movement.
Each has a clear place to enforce it. Name them.
Interviewer follow-up questions
For design problems, always anticipate these:
- "How would you add multiple elevators?" — a bank of elevators + a dispatcher. Introduces the "which elevator takes this call" problem. A new Strategy layer.
- "How would you handle express floors (skip some)?" — per-elevator config; SCAN skips not-allowed floors.
- "How would you handle door-open events?" — a new state (stopping-with-door-open). State pattern shines here.
Your design.md doesn't have to answer these — but if it puts your code in a position where answering them is easy, that's the extensibility signal interviewers care about.