Click Here To See The Project Codebase
Simulation of an elevator system by using approaches like Domain Driven Design, Design Patterns such as state, strategy and bridge patterns
This repository models an elevator system using domain-driven design concepts and a handful of classic object-oriented patterns. The code is structured to keep domain logic independent from the simulation driver and visualization, making it straightforward to extend with new policies, statistics, or elevator behaviors.
domain) – Entities such as Building, Elevator, Floor, and Person capture core behavior and state. Value objects like Weight, Patience, and movement/status enums encapsulate invariants around physical constraints and passenger temperament. Collections (e.g., FloorList, ElevatorList, People) coordinate multiple entities while keeping rules close to the domain.domain.policies) – Strategy implementations for dynamic decisions such as selecting an elevator (MostUnoccupied) or ordering waiting passengers (PersonSortPolicy and implementations). The ElevatorSelectionPolicy interface decouples selection logic from elevator control, enabling experiments with alternate heuristics.domain.elevatorstate) – Elevator motion and door behavior are modeled via the State pattern (GoingUp, GoingDown, WaitIdleOnZeroth, Fwt), keeping transition logic cohesive and swapping behaviors at runtime through Elevator.changeState.simulation) – The Simulator drives discrete time steps, delegating initialization and per-tick updates to Simulatable systems. The elevator-specific ElevatorSystem wires the building, advances the Clock, injects randomness, and orchestrates interplays between floors and elevators.simulation.elevator) – ElevatorSystemVisualizer provides a minimal console visualization and statistics printout to observe simulation progress.Building composes FloorList and ElevatorList, each responsible for initializing and updating its members while respecting the single responsibility principle. Floor tracks its own people, available elevators, and per-floor statistics while delegating collection-level rules to People and FloorStatistics.Weight and Patience encapsulate scalar properties with factory helpers and domain operations (addition/subtraction or decrementing patience). These objects avoid primitive obsession and centralize constraints like min/max values.ElevatorSelectionPolicy interface and its MostUnoccupied implementation illustrate domain services that decide how to assign elevators without embedding heuristic logic inside entities. Additional strategies can be added under domain/policies without touching elevator internals.domain.statistics (e.g., FloorStatistics, ElevatorStatistics) accumulate metrics such as waiting time or capacity usage. Floors and elevators update their statistics within their own lifecycle hooks, enabling reporting without leaking implementation details.Elevators hold a reference to an ElevatorState subtype that owns the transition logic for movement and door handling. For example, GoingUp moves to the next floor, handles terminal conditions, and switches to Fwt (open doors) or GoingDown as needed. The abstract base ElevatorState defines the update() contract, and each concrete state encapsulates one behavior mode. This design localizes complex branching and keeps Elevator simpler.
Elevator selection is decoupled by injecting an ElevatorSelectionPolicy into the Building/ElevatorList, letting simulations swap heuristics (e.g., distance-based or load-based) without code churn. Passenger ordering can likewise vary by providing different PersonSortPolicy implementations to organize boarding priority.
The Simulator class drives the simulation for a configured number of steps. Each iteration calls update() on the Simulatable system, optionally renders the state, and supports configurable pauses for readability. The elevator-specific system advances a shared Clock, spawns random people onto floors, updates elevator states, boards/disembarks riders, and manages patience timeouts each tick. This loop-oriented architecture keeps time progression explicit and testable.
ElevatorSystemVisualizer implements SystemVisualizer to print the current time and aggregated elevator/floor statistics each tick, using console utilities to keep output legible. Statistics generators on the lists feed the visualization layer without exposing raw internals, keeping a clean separation between core logic and UI concerns.
ElevatorSelectionPolicy implementation and injecting it in Main when constructing the ElevatorSystem. No other classes need changes thanks to the Strategy pattern.PersonSortPolicy and applying it within People or FloorList where queues are processed. This keeps boarding logic configurable.ElevatorState subclasses (e.g., maintenance mode or express service) and adjusting state transitions inside existing states to incorporate the new mode.domain.statistics classes or their generators in ElevatorList/FloorList. The visualization layer will surface new metrics automatically if included in the generated summaries.Main class: adjust numbers of floors/elevators, toggle the visualizer, change pause intervals, or plug different randomness sources to study system behavior.Main wires together the clock, randomness source, selection policy, elevator system, and simulator. Enabling displaySimulation prints periodic statistics, while pauseInterval slows the loop for readability. Adjust these values to run shorter or longer experiments or to disable visualization entirely for faster execution.