Elevator System
Problem Statement
Section titled “Problem Statement”Design an elevator control system for a building with multiple elevators. The system should efficiently handle user requests from different floors, optimize elevator movement to reduce wait times, and manage elevator states. Support both internal (inside elevator) and external (floor) requests.
Requirements
Section titled “Requirements”Functional Requirements
Section titled “Functional Requirements”- Handle multiple elevators in a building
- Process requests from floors (up/down buttons)
- Process requests from inside elevator (floor selection)
- Optimal elevator selection based on proximity and direction
- Support different elevator states: IDLE, MOVING_UP, MOVING_DOWN, MAINTENANCE
- Door open/close operations with safety checks
- Emergency stop functionality
- Maximum capacity enforcement
Non-Functional Requirements
Section titled “Non-Functional Requirements”- Minimize average wait time
- Thread-safe for concurrent requests
- Efficient scheduling algorithm
- Real-time status updates
- Fault-tolerant system
Simplified Class Diagram
Section titled “Simplified Class Diagram”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
skinparam classBorderThickness 3skinparam ArrowThickness 1skinparam defaultFontSize 16skinparam classAttributeFontSize 18skinparam classFontSize 16
class ElevatorSystem { + requestElevator() + assignElevator() + processRequest()}
class Elevator { + move() + openDoor() + closeDoor() + addRequest()}
class ElevatorController { + selectOptimalElevator() + manageQueue()}
class Request { + getSourceFloor() + getDestinationFloor() + getDirection()}
class Floor { + pressUpButton() + pressDownButton()}
class Door { + open() + close()}
ElevatorSystem *-- ElevatorControllerElevatorSystem o-- ElevatorElevatorController ..> RequestElevator *-- DoorElevator --> RequestFloor ..> Request
@endumlSimplified Overview
Section titled “Simplified Overview”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam componentStyle rectangle
package "System Management" { [ElevatorSystemService] as System}
package "Elevator Components" { interface "IElevatorCar" as Car interface "IElevatorController" as Controller interface "IDoorController" as Door}
package "Building Structure" { [Floor]}
package "User Interface" { interface "IPanel" as Panel interface "IDisplay" as Display interface "IButton" as Button}
package "Strategy" { interface "ISelectionStrategy" as StrategyIntf}
[ElevatorSystemDriver] --> System : usesSystem *-- Car : managesSystem *-- Controller : managesSystem *-- Floor : managesSystem *-- StrategyIntf : composed ofCar *-- Door : composed ofCar *-- Display : composed ofController o-- Car : controlsFloor o-- Button : hasFloor o-- Display : has
@endumlDetailed Class Diagram
Section titled “Detailed Class Diagram”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
enum Direction { UP DOWN IDLE}
enum ElevatorState { IDLE MOVING_UP MOVING_DOWN MAINTENANCE EMERGENCY}
enum DoorState { OPEN CLOSED OPENING CLOSING}
class Request { - sourceFloor: int - destinationFloor: int - direction: Direction - timestamp: DateTime + Request(sourceFloor: int, destinationFloor: int) + getDirection(): Direction + getSourceFloor(): int}
interface IElevatorCar { + getId(): String + getCurrentFloor(): int + getState(): ElevatorState + addRequest(floor: int): void + isMovingTowards(floor: int, direction: Direction): boolean + hasCapacity(): boolean}
class ElevatorCar { - id: String - currentFloor: int - state: ElevatorState - doorController: IDoorController - displayPanel: IDisplay - currentCapacity: int - maxCapacity: int - requests: PriorityQueue<Integer> + ElevatorCar(id: String, maxCapacity: int, doorCtrl: IDoorController, display: IDisplay) + move(): void + addRequest(floor: int): void + getCurrentFloor(): int + getState(): ElevatorState + isMovingTowards(floor: int, direction: Direction): boolean + hasCapacity(): boolean}
interface IDoorController { + open(): void + close(): void + getState(): DoorState + forceOpen(): void}
class DoorController { - state: DoorState - sensor: IDoorSensor + DoorController(sensor: IDoorSensor) + open(): void + close(): void + getState(): DoorState + forceOpen(): void}
interface IDoorSensor { + isObstructed(): boolean}
class DoorSensor { + isObstructed(): boolean}
interface IButton { + press(): void + reset(): void + isPressed(): boolean}
class FloorButton { - floor: int - direction: Direction - pressed: boolean + FloorButton(floor: int, direction: Direction) + press(): void + reset(): void + isPressed(): boolean}
class ElevatorButton { - destinationFloor: int - pressed: boolean + ElevatorButton(floor: int) + press(): void + reset(): void + isPressed(): boolean}
interface IPanel { + selectFloor(floor: int): void + emergency(): void}
class ElevatorPanel { - buttons: Map<Integer, ElevatorButton> - controller: IElevatorController + ElevatorPanel(controller: IElevatorController) + selectFloor(floor: int): void + emergency(): void}
class Floor { - floorNumber: int - upButton: FloorButton - downButton: FloorButton - display: IDisplay + Floor(floorNumber: int, display: IDisplay) + requestUp(): void + requestDown(): void + getFloorNumber(): int}
interface IElevatorController { + acceptRequest(floor: int): void + start(): void + stop(): void}
class ElevatorController { - elevator: IElevatorCar - requestQueue: Queue<Integer> - running: AtomicBoolean + ElevatorController(elevator: IElevatorCar) + acceptRequest(floor: int): void + start(): void + stop(): void - processNextRequest(): void - shouldStop(floor: int): boolean}
interface ISelectionStrategy { + selectElevator(elevators: List<IElevatorCar>, request: Request): IElevatorCar}
class NearestElevatorStrategy { + selectElevator(elevators: List<IElevatorCar>, request: Request): IElevatorCar}
class ZoneBasedStrategy { - zones: Map<Integer, List<IElevatorCar>> + selectElevator(elevators: List<IElevatorCar>, request: Request): IElevatorCar}
interface IDisplay { + update(floor: int, direction: Direction): void + show(message: String): void}
class ElevatorDisplay { + update(floor: int, direction: Direction): void + show(message: String): void}
class FloorDisplay { + update(floor: int, direction: Direction): void + show(message: String): void}
interface IElevatorSystem { + requestElevator(floor: int, direction: Direction): void + addElevator(elevator: IElevatorCar, controller: IElevatorController): void + getElevatorStatus(): Map<String, String>}
class ElevatorSystemService { - elevators: List<IElevatorCar> - controllers: Map<String, IElevatorController> - floors: List<Floor> - selectionStrategy: ISelectionStrategy + ElevatorSystemService(strategy: ISelectionStrategy) + requestElevator(floor: int, direction: Direction): void + addElevator(elevator: IElevatorCar, controller: IElevatorController): void + addFloor(floor: Floor): void + getElevatorStatus(): Map<String, String>}
class ElevatorSystemDriver { + {static} main(args: String[]): void - setupElevatorSystem(): IElevatorSystem - simulateRequests(): void}
Request *-- Direction
IElevatorCar <|.. ElevatorCarElevatorCar *-- ElevatorStateElevatorCar *-- IDoorController : composed ofElevatorCar *-- IDisplay : composed of
IDoorController <|.. DoorControllerDoorController *-- DoorStateDoorController o-- IDoorSensor : usesIDoorSensor <|.. DoorSensor
IButton <|.. FloorButtonIButton <|.. ElevatorButtonFloorButton *-- Direction
IPanel <|.. ElevatorPanelElevatorPanel o-- ElevatorButton : hasElevatorPanel o-- IElevatorController : uses
Floor o-- FloorButton : hasFloor o-- IDisplay : has
IElevatorController <|.. ElevatorControllerElevatorController o-- IElevatorCar : controls
ISelectionStrategy <|.. NearestElevatorStrategyISelectionStrategy <|.. ZoneBasedStrategy
IDisplay <|.. ElevatorDisplayIDisplay <|.. FloorDisplay
IElevatorSystem <|.. ElevatorSystemServiceElevatorSystemService *-- IElevatorCar : managesElevatorSystemService *-- IElevatorController : managesElevatorSystemService *-- Floor : managesElevatorSystemService *-- ISelectionStrategy : composed of
ElevatorSystemDriver ..> IElevatorSystem : usesElevatorSystemDriver ..> IElevatorCar : createsElevatorSystemDriver ..> IElevatorController : creates
@endumlKey Design Patterns
Section titled “Key Design Patterns”- Singleton Pattern: ElevatorSystem as single control point
- Strategy Pattern: Different elevator selection algorithms
- State Pattern: Elevator and door state management
- Observer Pattern: Display updates when elevator moves
Design Pattern Diagrams
Section titled “Design Pattern Diagrams”1. Strategy Pattern - Elevator Selection Algorithm
Section titled “1. Strategy Pattern - Elevator Selection Algorithm”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
title Strategy Pattern - Elevator Selection
interface ISelectionStrategy { + selectElevator(List<IElevatorCar>, Request): IElevatorCar}
class ShortestDistanceStrategy { + selectElevator(List<IElevatorCar>, Request): IElevatorCar}
class LeastLoadedStrategy { + selectElevator(List<IElevatorCar>, Request): IElevatorCar}
class ZoneBasedStrategy { + selectElevator(List<IElevatorCar>, Request): IElevatorCar}
class ElevatorSystemService { - selectionStrategy: ISelectionStrategy - elevators: List<IElevatorCar> + setSelectionStrategy(ISelectionStrategy): void + requestElevator(floor, direction): void}
ISelectionStrategy <|.. ShortestDistanceStrategyISelectionStrategy <|.. LeastLoadedStrategyISelectionStrategy <|.. ZoneBasedStrategyElevatorSystemService *-- ISelectionStrategy
note right of ShortestDistanceStrategy Selects elevator with minimum distance to requested floorend note
note right of LeastLoadedStrategy Selects elevator with fewest pending requests (load balancing)end note
note right of ZoneBasedStrategy Divides building into zones, assigns specific elevators to each zoneend note
note bottom of ElevatorSystemService **Code Example:**
// Office building: use shortest distance system.setSelectionStrategy(new ShortestDistanceStrategy());
// Hotel: balance load across all elevators system.setSelectionStrategy(new LeastLoadedStrategy());
// Skyscraper: zone-based (floors 1-20, 21-40, etc.) system.setSelectionStrategy(new ZoneBasedStrategy());
// Strategy changes behavior without changing client code system.requestElevator(15, Direction.UP);end note
@enduml2. State Pattern - Elevator State Management
Section titled “2. State Pattern - Elevator State Management”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
title State Pattern - Elevator States
enum ElevatorState { IDLE MOVING_UP MOVING_DOWN STOPPED MAINTENANCE}
enum DoorState { OPEN CLOSED OPENING CLOSING}
class ElevatorCar { - currentState: ElevatorState - doorState: DoorState - currentFloor: int + moveUp(): void + moveDown(): void + stop(): void + openDoors(): void + closeDoors(): void + handleStateTransition(): void}
class DoorController { - state: DoorState + open(): void + close(): void + canOpen(): boolean + canClose(): boolean}
ElevatorCar *-- ElevatorStateElevatorCar *-- DoorControllerDoorController *-- DoorState
note top of ElevatorState State Transitions: IDLE -> MOVING_UP/DOWN MOVING -> STOPPED STOPPED -> IDLE or MOVINGend note
note bottom of ElevatorCar **Code Example:**
ElevatorCar elevator = new ElevatorCar(1);
// State: IDLE, DoorState: CLOSED elevator.addRequest(5);
// State changes: IDLE -> MOVING_UP elevator.move();
// Reaches floor 5 // State: MOVING_UP -> STOPPED elevator.stop();
// Door state: CLOSED -> OPENING -> OPEN elevator.openDoors();
// Wait for passengers Thread.sleep(3000);
// Door state: OPEN -> CLOSING -> CLOSED elevator.closeDoors();
// State: STOPPED -> IDLE (no more requests)end note
@enduml3. Observer Pattern - Display Updates
Section titled “3. Observer Pattern - Display Updates”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
title Observer Pattern - Elevator Display
interface IElevatorObserver { + onFloorChanged(elevatorId, floor): void + onDirectionChanged(elevatorId, direction): void + onDoorStateChanged(elevatorId, doorState): void}
class ElevatorCar { - observers: List<IElevatorObserver> - currentFloor: int + addObserver(IElevatorObserver): void + removeObserver(IElevatorObserver): void - notifyFloorChange(): void + moveToFloor(floor): void}
class FloorDisplay { - floorNumber: int + onFloorChanged(elevatorId, floor): void + updateDisplay(floor): void}
class CarDisplay { - elevatorId: String + onFloorChanged(elevatorId, floor): void + onDirectionChanged(elevatorId, direction): void}
class MonitoringSystem { + onFloorChanged(elevatorId, floor): void + logElevatorMovement(): void}
ElevatorCar o-- "*" IElevatorObserver : notifiesIElevatorObserver <|.. FloorDisplayIElevatorObserver <|.. CarDisplayIElevatorObserver <|.. MonitoringSystem
note bottom of ElevatorCar **Code Example:**
ElevatorCar elevator = new ElevatorCar("E1");
// Register observers elevator.addObserver(new FloorDisplay(1)); elevator.addObserver(new FloorDisplay(5)); elevator.addObserver(new CarDisplay("E1")); elevator.addObserver(new MonitoringSystem());
// Movement triggers notifications to all observers elevator.moveToFloor(5);
// All displays update automatically: // - Floor 1 display: "↑ 2, 3, 4..." // - Floor 5 display: "Arriving" // - Car display: "Floor 5" // - Monitoring: Logs movementend note
@endumlCode Snippets
Section titled “Code Snippets”Elevator Movement Logic
Section titled “Elevator Movement Logic”public class ElevatorCar { public void move() { if (requests.isEmpty()) { state = ElevatorState.IDLE; return; }
int targetFloor = requests.peek();
if (currentFloor < targetFloor) { state = ElevatorState.MOVING_UP; currentFloor++; } else if (currentFloor > targetFloor) { state = ElevatorState.MOVING_DOWN; currentFloor--; } else { // Reached target floor requests.poll(); openDoor(); // Wait for passengers closeDoor(); }
display.update(currentFloor, getDirection()); }
public boolean isMovingTowards(int floor, Direction direction) { if (state == ElevatorState.IDLE) { return true; }
if (direction == Direction.UP) { return state == ElevatorState.MOVING_UP && currentFloor < floor; } else { return state == ElevatorState.MOVING_DOWN && currentFloor > floor; } }}Elevator Selection Strategy
Section titled “Elevator Selection Strategy”public class NearestElevatorStrategy implements ElevatorSelectionStrategy { @Override public ElevatorCar selectElevator(List<ElevatorCar> elevators, Request request) { ElevatorCar bestElevator = null; int minDistance = Integer.MAX_VALUE;
for (ElevatorCar elevator : elevators) { if (!elevator.hasCapacity()) { continue; }
// Prefer elevators already moving in the same direction if (elevator.isMovingTowards(request.getSourceFloor(), request.getDirection())) { int distance = Math.abs(elevator.getCurrentFloor() - request.getSourceFloor()); if (distance < minDistance) { minDistance = distance; bestElevator = elevator; } } }
// If no suitable elevator found, select nearest idle elevator if (bestElevator == null) { for (ElevatorCar elevator : elevators) { if (elevator.getState() == ElevatorState.IDLE) { int distance = Math.abs(elevator.getCurrentFloor() - request.getSourceFloor()); if (distance < minDistance) { minDistance = distance; bestElevator = elevator; } } } }
return bestElevator; }}Request Processing
Section titled “Request Processing”public class ElevatorSystem { public void requestElevator(int floor, Direction direction) { Request request = new Request(floor, -1); request.setDirection(direction);
ElevatorCar selectedElevator = selectionStrategy.selectElevator(elevators, request);
if (selectedElevator != null) { selectedElevator.addRequest(floor); logger.info("Assigned elevator " + selectedElevator.getId() + " to floor " + floor); } else { logger.warning("No available elevator for floor " + floor); } }}Extension Points
Section titled “Extension Points”- Add predictive algorithms for peak hours
- Implement energy-saving mode during low usage
- Add priority handling for VIP floors
- Support express elevators (skip certain floors)
- Implement load balancing across elevators
- Add destination dispatch system (group passengers by destination)
- Include elevator maintenance scheduling