Skip to main content

LLD - Elevator System

Requirements

  • The building has multiple floors and elevators.
  • Elevators can move up and down, stop at floors, and open/close doors.
  • Users can request elevators from any floor (hall call) and select their destination floor inside the elevator (cabin call).
  • The system should efficiently schedule elevator movements based on requests.

Class Diagram

image

Implementation

ElevatorSystem

ElevatorSystem Singleton Class:

  • Manages all elevators and handles requests.
  • Uses the Singleton pattern to ensure only one instance exists.
  • Delegates scheduling to a Scheduler interface.
import java.util.ArrayList;
import java.util.List;

public class ElevatorSystem {
    private static ElevatorSystem instance;
    private List<Elevator> elevators;
    private Scheduler scheduler;

    private ElevatorSystem(int numberOfElevators) {
        elevators = new ArrayList<>();
        scheduler = new DefaultScheduler();
        for (int i = 1; i <= numberOfElevators; i++) {
            elevators.add(new Elevator(i));
        }
    }

    public static ElevatorSystem getInstance(int numberOfElevators) {
        if (instance == null) {
            instance = new ElevatorSystem(numberOfElevators);
        }
        return instance;
    }

    public void pickupRequest(int floor, Direction direction) {
        int elevatorId = scheduler.scheduleElevator(elevators, floor, direction);
        System.out.println("Elevator " + elevatorId + " is assigned to floor " + floor);
        elevators.get(elevatorId - 1).addDestination(floor);
    }

    public void destinationRequest(int elevatorId, int floor) {
        elevators.get(elevatorId - 1).addDestination(floor);
    }

    public void step() {
        elevators.forEach(Elevator::move);
    }

    public List<Elevator> getElevators() {
        return elevators;
    }
}

Elevator

Elevator Class:

  • Represents an individual elevator.
  • Maintains its current state and requested floors.
  • Implements movement logic.
import java.util.PriorityQueue;

public class Elevator {
    private int id;
    private int currentFloor;
    private Direction direction;
    private ElevatorStatus status;
    private PriorityQueue<Integer> requestedFloors;

    public Elevator(int id) {
        this.id = id;
        this.currentFloor = 0;
        this.direction = Direction.IDLE;
        this.status = ElevatorStatus.IDLE;
        this.requestedFloors = new PriorityQueue<>();
    }

    public void addDestination(int floor) {
        requestedFloors.offer(floor);
        if (status == ElevatorStatus.IDLE) {
            status = ElevatorStatus.MOVING;
        }
    }

    public void move() {
        if (requestedFloors.isEmpty()) {
            status = ElevatorStatus.IDLE;
            direction = Direction.IDLE;
            return;
        }

        int destinationFloor = requestedFloors.peek();

        if (currentFloor < destinationFloor) {
            direction = Direction.UP;
            currentFloor++;
        } else if (currentFloor > destinationFloor) {
            direction = Direction.DOWN;
            currentFloor--;
        }

        System.out.println("Elevator " + id + " is at floor " + currentFloor);

        if (currentFloor == destinationFloor) {
            requestedFloors.poll();
            System.out.println("Elevator " + id + " has arrived at floor " + currentFloor);
        }
    }

    // Getters and Setters
    public int getId() {
        return id;
    }

    public int getCurrentFloor() {
        return currentFloor;
    }

    public Direction getDirection() {
        return direction;
    }

    public ElevatorStatus getStatus() {
        return status;
    }
}

Scheduler / Dispatcher

Scheduler Interface and DefaultScheduler:

  • Strategy pattern allows different scheduling algorithms.
  • DefaultScheduler provides a basic implementation.
import java.util.List;

public interface Scheduler {
    int scheduleElevator(List<Elevator> elevators, int floor, Direction direction);
}

public class DefaultScheduler implements Scheduler {
    @Override
    public int scheduleElevator(List<Elevator> elevators, int floor, Direction direction) {
        // Simple scheduling algorithm: find the closest idle or moving elevator
        int minDistance = Integer.MAX_VALUE;
        int selectedElevatorId = -1;

        for (Elevator elevator : elevators) {
            int distance = Math.abs(elevator.getCurrentFloor() - floor);
            if (distance < minDistance) {
                minDistance = distance;
                selectedElevatorId = elevator.getId();
            }
        }

        return selectedElevatorId;
    }
}

Driver and Enums

State Management for Direction. This is used to display status.

public enum Direction {
    UP,
    DOWN,
    IDLE
}

State of Elevator

public enum ElevatorStatus {
    MOVING,
    STOPPED,
    IDLE
}

Concurrency Concerns

We need to implement concurrent collections and thread safe code blocks to ensure that critical resources are correctly accessed.

Comments

Comments powered by Disqus