Elevator System
Design an elevator control system for a building with N elevators and F floors. Riders press hall buttons on each floor (up/down) and car buttons inside each elevator. The system must dispatch efficiently and serve every request.
Clarifying questions
- How many elevators and floors? Are there express elevators or zones?
- Are we optimizing for average wait time, throughput, or energy?
- Do we handle VIP/service modes or just normal operation?
- Is the scheduler centralized or does each elevator decide independently?
- Do we need to model door open/close timing and capacity limits?
Core requirements
- Accept hall requests (floor + direction) and car requests (target floor).
- Dispatch an elevator to each hall request using a defined policy.
- Track each elevator's position, direction, and pending stops.
- Open/close doors at stops and handle capacity overflow.
- Allow plug-in of different scheduling algorithms (SCAN, nearest-car, look-ahead).
- Surface diagnostics (idle elevators, longest waits) for monitoring.
Canonical class breakdown
Building — Owns the set of Elevators and Floors and routes hall calls into the Dispatcher.
Elevator — Single car with current floor, direction, capacity, and an ordered set of pending stops.
Floor — Hall call buttons (up/down) and the up/down indicators; emits HallRequest events.
Request (HallRequest, CarRequest) — Value object representing a single ask; distinguishing hall vs car matters for scheduling.
Dispatcher — Owns the scheduling decision: given system state and a request, picks the elevator.
SchedulingStrategy (interface) — Pluggable algorithm (nearest-car, SCAN, hybrid) consumed by Dispatcher.
ElevatorController — Per-elevator state machine that consumes assigned stops and drives door/motor commands.
Java sketchjava
// Java skeleton
enum Direction { UP, DOWN, IDLE }
abstract class Request {
protected final Instant createdAt;
}
class HallRequest extends Request {
private final int floor;
private final Direction direction;
}
class CarRequest extends Request {
private final int elevatorId;
private final int targetFloor;
}
class Floor {
private final int number;
private boolean upLit;
private boolean downLit;
public HallRequest pressUp() { ... }
public HallRequest pressDown() { ... }
}
class Elevator {
private final int id;
private int currentFloor;
private Direction direction;
private final int capacity;
private int occupancy;
private final TreeSet<Integer> pendingStops; // re-sorted on direction flip
public void addStop(int floor) { ... }
public int nextStop() { ... }
}
interface SchedulingStrategy {
Elevator pick(List<Elevator> cars, HallRequest req);
}
class Dispatcher {
private final List<Elevator> elevators;
private final SchedulingStrategy strategy;
public void submit(HallRequest req) { /* strategy.pick then assign */ }
}
class ElevatorController {
private final Elevator elevator;
public void tick() { /* move, open doors, close, advance state machine */ }
private void openDoors() { ... }
private void closeDoors() { ... }
}
class Building {
private final List<Floor> floors;
private final List<Elevator> elevators;
private final Dispatcher dispatcher;
public void requestHall(int floor, Direction dir) { ... }
public void requestCar(int elevatorId, int target) { ... }
}
Key decisions to defend
- Separate Dispatcher (assignment) from ElevatorController (execution) — they change for different reasons.
- SchedulingStrategy is Strategy because the right algorithm depends on building shape and time of day.
- Hall and Car requests are distinct types: car requests are committed work, hall requests are still assignable.
- Elevator's pending stops is a sorted set keyed by direction, not a queue — re-sort on direction change.
- Keep door/motor timing inside ElevatorController as a state machine; don't leak it into Dispatcher.
Likely follow-ups
- · Building has a lobby surge at 9am — how does the strategy adapt?
- · One elevator fails mid-trip — how do you reassign its committed stops?
- · Add destination-dispatch (rider enters target on the hall panel) — what changes?
Dive deeper
This question probes whether you can separate decision (who serves this call) from execution (how does that car physically get there). Weak designs glue scheduling into Elevator and can't swap algorithms. The deeper test is whether you treat hall calls and car calls as different first-class concepts — interviewers know that conflating them is the most common modeling bug.