LLD Hub
lldstate-machinecommand-pattern

How to Design an Elevator System | LLD Interview Guide

Design a multi-elevator control system with optimal assignment, SCAN algorithm, and State pattern. Detailed class breakdown for advanced LLD rounds.

4 April 2025·8 min read

Practice this problem

Elevator System — get AI-scored feedback on your solution

Solve it →

The Elevator System is one of the most challenging LLD problems because it requires modeling a real-time control system with multiple concurrent actors. It tests your understanding of the State pattern, scheduling algorithms, and clean separation of concerns. Let's break it down completely.

Core Requirements

  • Multiple elevators serving a building with multiple floors
  • External requests: Up/Down buttons on each floor
  • Internal requests: Floor buttons inside the elevator
  • Assign the optimal elevator to each request
  • Elevator states: Moving Up, Moving Down, Idle
  • Door logic: open/close with 5-second safety timeout
  • Emergency stop halts all elevators

Core Entities

  • Building — has floors and an ElevatorController
  • Floor — has Up and Down request buttons
  • Elevator — has a state, current floor, and destination queue
  • ElevatorController — receives requests, assigns elevators
  • Request — either an external (floor button) or internal (panel) request
  • Door — manages open/close with timeout

Elevator State Machine

enum ElevatorState { IDLE, MOVING_UP, MOVING_DOWN, DOORS_OPEN }

class Elevator {
  currentFloor: number;
  state: ElevatorState;
  destinationQueue: number[];  // sorted floors to visit

  addDestination(floor: number): void {
    if (!this.destinationQueue.includes(floor)) {
      this.destinationQueue.push(floor);
      this.sortQueue(); // SCAN algorithm
    }
  }

  move(): void {
    if (this.destinationQueue.length === 0) {
      this.state = ElevatorState.IDLE; return;
    }
    const next = this.destinationQueue[0];
    if (next > this.currentFloor) this.state = ElevatorState.MOVING_UP;
    if (next < this.currentFloor) this.state = ElevatorState.MOVING_DOWN;
    this.currentFloor = next;
    this.destinationQueue.shift();
    this.openDoors();
  }
}

Elevator Assignment Strategy

The assignment algorithm is a great place to use the Strategy pattern:

interface ElevatorSelectionStrategy {
  select(request: Request, elevators: Elevator[]): Elevator;
}

class NearestElevatorStrategy implements ElevatorSelectionStrategy {
  select(request: Request, elevators: Elevator[]): Elevator {
    return elevators
      .filter(e => e.state !== ElevatorState.DOORS_OPEN)
      .sort((a, b) =>
        Math.abs(a.currentFloor - request.floor) -
        Math.abs(b.currentFloor - request.floor)
      )[0];
  }
}

class SCANStrategy implements ElevatorSelectionStrategy {
  // Assigns elevator already moving in the same direction, if between current and destination
  select(request: Request, elevators: Elevator[]): Elevator { ... }
}

Command Pattern for Requests

interface ElevatorCommand { execute(elevator: Elevator): void; }

class GoToFloorCommand implements ElevatorCommand {
  constructor(private floor: number) {}
  execute(elevator: Elevator) { elevator.addDestination(this.floor); }
}

class EmergencyStopCommand implements ElevatorCommand {
  execute(elevator: Elevator) { elevator.emergencyStop(); }
}

Common Mistakes

  • Not using a destination queue — elevators need to serve multiple floors in one trip
  • Ignoring direction when assigning — an elevator moving up past floor 3 shouldn't be assigned a downward request from floor 2
  • Forgetting door timeout — doors must auto-close, this is a State transition

Ready to practice?

Submit your solution and get AI-scored feedback on OOP, SOLID principles, design patterns, and code quality.

Solve Elevator System