Design Example: Elevator System
Designing an Elevator System is a sophisticated OOD challenge that tests your ability to handle real-time requests, state management, and multi-object coordination.
Step 1: Requirements Gathering
Core Use Cases:
- User presses a button on a floor to go up or down.
- User inside the elevator selects a destination floor.
- The system dispatches the most suitable elevator.
- Elevators open/close doors and move between floors.
Clarifications:
- How many elevators? (Multiple)
- What is the dispatching goal? (Minimize wait time vs. minimize energy)
- Support for emergency stops/overload? (Basic support)
Step 2: Identify Core Objects
- Elevator: Represents the physical car with a current floor, direction, and state.
- Button: Can be
ExternalButton(on floors) orInternalButton(inside the car). - Floor: Represents a level in the building.
- ElevatorController: Manages a single elevator's movement.
- ElevatorSystem (Dispatcher): Orchestrates multiple elevators.
Step 3: Design Class Diagram
Step 4: Implementation in TypeScript
enum Direction { UP, DOWN, IDLE }
enum Status { MOVING, STOPPED, MAINTENANCE }
class Elevator {
private currentFloor: number = 0;
private direction: Direction = Direction.IDLE;
private requests: Set<number> = new Set();
public addRequest(floor: number) {
this.requests.add(floor);
}
public move() {
// Basic movement logic
if (this.requests.size === 0) return;
// Logic to update currentFloor and direction
}
public getCurrentFloor() { return this.currentFloor; }
public getDirection() { return this.direction; }
}
interface DispatchStrategy {
pickElevator(elevators: Elevator[], floor: number, dir: Direction): Elevator;
}
class ClosestIdleStrategy implements DispatchStrategy {
pickElevator(elevators: Elevator[], floor: number, dir: Direction): Elevator {
// Find the closest elevator that is IDLE or moving in the same direction
return elevators.reduce((prev, curr) => {
const prevDist = Math.abs(prev.getCurrentFloor() - floor);
const currDist = Math.abs(curr.getCurrentFloor() - floor);
return currDist < prevDist ? curr : prev;
});
}
}
class ElevatorSystem {
private static instance: ElevatorSystem;
private elevators: Elevator[] = [];
private strategy: DispatchStrategy;
private constructor() {
this.strategy = new ClosestIdleStrategy();
for (let i = 0; i < 3; i++) this.elevators.push(new Elevator());
}
public static getInstance() {
if (!this.instance) this.instance = new ElevatorSystem();
return this.instance;
}
public requestElevator(floor: number, direction: Direction) {
const selected = this.strategy.pickElevator(this.elevators, floor, direction);
selected.addRequest(floor);
}
}Deep Dive: Dispatching Algorithms
- FCFS (First-Come, First-Served): Simple but inefficient (starvation).
- SCAN (Elevator Algorithm): The elevator moves in one direction until it hits the end, then reverses.
- LOOK: Similar to SCAN but reverses as soon as there are no more requests in the current direction.
Wrap Up
An Elevator System is essentially a scheduling problem. By separating the DispatchStrategy from the ElevatorSystem, you make your design flexible and testable—which is exactly what interviewers look for.
[!IMPORTANT] In a high-traffic building, you might implement Destination Dispatching where users input their floor before entering the elevator to group passengers intelligently.