Design a Traffic Control System
OOP design for a traffic signal control system covering intersection modeling, signal state machines, phase scheduling, emergency vehicle preemption, and adaptive timing.
The Problem
Your city's transportation department manages 200 intersections with aging traffic controllers. During rush hour, northbound traffic backs up for eight blocks because the signals run on fixed 60-second cycles regardless of actual demand. When an ambulance approaches, it has no way to preempt the red light, and drivers freeze in confusion. The mayor wants a modern system where signals adapt to real-time traffic flow and emergency vehicles get guaranteed green corridors.
A traffic control system looks simple on the surface: lights turn red, yellow, green. But underneath, each intersection runs a phase cycle where groups of signals change together (northbound and southbound go green while eastbound and westbound stay red). Phases have minimum and maximum durations, transitions must respect yellow clearance intervals, and an emergency vehicle can override everything mid-cycle. Multiply that across dozens of intersections and the coordination problem gets serious fast.
Design the core classes for a traffic control system that handles signal state machines, phase-based scheduling, configurable timing plans, sensor-driven adaptive timing, and emergency vehicle preemption.
Requirements
Clarifying Questions
Before jumping into class design, ask questions to turn the vague prompt into a concrete specification. Cover four areas: core actions, error handling, boundaries, and future extensions.
You: "Are we designing for a single intersection or a network of intersections?"
Interviewer: "Start with a single intersection. The design should make it straightforward to extend to a network later, but focus on one intersection with multiple roads."
Good. Single intersection keeps scope manageable, but we need to think about composition for later. Each intersection is a self-contained unit.
You: "How many roads meet at an intersection? Is it always a four-way?"
Interviewer: "Typically four-way, but support three-way (T-intersections) as well. Each road has a traffic signal controlling it."
Variable road count per intersection. The system cannot hardcode four roads; it must handle any number.
You: "What states does a traffic signal cycle through?"
Interviewer: "RED, GREEN, and YELLOW. Each state has a configurable duration. A signal transitions GREEN to YELLOW to RED, and then waits for another phase to activate it."
Three-state machine with configurable durations. The key insight: a signal does not cycle on its own. The phase controller tells it when to go green, and the signal handles its own GREEN-to-YELLOW-to-RED decay.
You: "What is a 'phase' exactly? How do phases relate to signals?"
Interviewer: "A phase is a group of signals that are green at the same time. For a standard four-way intersection, Phase 1 might be north-south green while east-west is red, and Phase 2 is the reverse. Phases cycle in order."
Phases group signals. This is critical. You never set individual signals directly; you activate a phase, and the phase controls which signals are green. That prevents conflicting greens.
You: "How should the system decide how long each phase runs? Fixed timers only?"
Interviewer: "Support multiple scheduling strategies. At minimum: fixed-cycle timing, time-of-day schedules (longer green for the busy direction during rush hour), and sensor-adaptive timing where the system extends a green phase if sensors detect waiting vehicles."
Three scheduling strategies with runtime selection. Strategy pattern fits here. The sensor-adaptive mode is the most interesting because it reacts to real-time data.
You: "How do emergency vehicles get priority?"
Interviewer: "When an emergency vehicle approaches, the system overrides the current phase. It transitions any conflicting signals to red, gives the emergency vehicle's direction a green, and resumes normal scheduling once the vehicle passes."
Emergency preemption interrupts the normal cycle, forces a specific phase, then restores the previous state. This is a temporary override, not a permanent schedule change.
You: "Do we need pedestrian signals or left-turn arrows?"
Interviewer: "Out of scope for the core design, but the architecture should support adding them later."
Perfect. You have now clarified scope and ruled out unnecessary complexity.
Final Requirements
Functional Requirements:
- Each intersection has N roads, each with a traffic signal that cycles through RED, GREEN, YELLOW
- Signals are grouped into phases; activating a phase sets its signals to GREEN and all others to RED
- Phases cycle in a configurable order with configurable durations per signal state
- Support fixed-cycle, time-of-day, and sensor-adaptive scheduling strategies
- Emergency preemption overrides the current phase, grants green to the emergency direction, and restores normal operation afterward
- Sensors detect vehicle presence and notify the controller to extend or trigger phases
Non-Functional Requirements:
- Thread safety: emergency preemption can arrive at any time during normal cycling
- Extensibility: adding pedestrian signals, left-turn phases, or intersection networking should not require rewriting existing classes
- No conflicting greens: the system must guarantee that orthogonal directions never have green simultaneously
Out of Scope:
- UI rendering or physical hardware control
- Persistence or database
- Pedestrian signals (discussed in Extensibility)
- Multi-intersection coordination / green wave (discussed in Extensibility)
Example Inputs and Outputs
Scenario 1: Normal fixed-cycle operation
- Setup: Four-way intersection with Phase A (north-south green) and Phase B (east-west green). Fixed cycle: 30s green, 5s yellow per phase.
- Expected: Phase A activates. N-S signals go GREEN for 30s, then YELLOW for 5s, then RED. Phase B activates. E-W signals go GREEN for 30s, then YELLOW for 5s, then RED. Cycle repeats.
- Why: Validates the basic phase cycling and signal state machine.
Scenario 2: Emergency preemption
- Setup: Phase A is active (N-S green, 15 seconds remaining). An ambulance approaches from the east.
- Expected: System interrupts Phase A. N-S signals transition to YELLOW then RED. E-W signals go GREEN. Ambulance passes. System resumes Phase A or advances to Phase B depending on policy.
- Why: Validates that preemption overrides normal scheduling and restores afterward.
Scenario 3: Sensor-adaptive extension
- Setup: Phase A is active with 5 seconds remaining. Sensor on the northbound road detects 10 waiting vehicles.
- Expected: Controller extends Phase A by up to the maximum extension time (e.g., 15s). If no more vehicles are detected, Phase A ends and Phase B begins.
- Why: Validates sensor-driven adaptive timing.
Try It Yourself
Try it yourself
Before reading the solution, spend 15-20 minutes sketching your own class diagram. Focus on the relationship between signals, phases, and the scheduling strategy. How do you prevent two conflicting phases from being active at the same time? Compare your approach with the walkthrough below.
Step 1: Identify Core Entities
Start by asking: what are the main "things" in this problem? Look at your requirements and pull out the nouns. Each noun is a candidate entity, and each entity should have a single, clear job.
A common mistake is cramming all the logic into one giant TrafficController class. Good design means the signal knows how to manage its own state machine, the phase knows which signals it groups, and the controller just orchestrates the cycle.
| Entity | Responsibility | Key attributes |
|---|---|---|
| TrafficControlSystem | Top-level orchestrator. Holds intersections, starts/stops the system. | intersections, running |
| Intersection | Manages one physical intersection. Owns roads, phases, and the active schedule. | roads, phases, scheduler, currentPhase |
| Road | Represents one approach to the intersection. Holds a signal and optional sensor. | name, signal, sensor |
| TrafficSignal | The state machine for one signal. Manages RED/GREEN/YELLOW transitions. | state, greenDuration, yellowDuration |
| SignalState | Enum of signal states: RED, GREEN, YELLOW. | (enum values) |
| Phase | A group of roads whose signals go green together. | name, roads, greenDuration, yellowDuration |
| Schedule | Ordered list of phases that defines the cycle. | phases |
| SchedulingStrategy | Interface for deciding how long each phase runs and when to advance. | (strategy methods) |
| Sensor | Detects vehicle presence on a road and notifies the controller. | road, vehicleCount |
| EmergencyOverride | Captures preemption state: which direction needs green, and what to restore. | emergencyRoad, previousPhase |
Notice that Phase groups roads, not signals directly. This is intentional: when you activate a phase, you are saying "these roads get green." The phase then delegates to each road's signal. If a road later gains a pedestrian signal or a left-turn arrow, the phase does not need to change.
Step 2: Define Relationships and Class Design
Class Diagram
Signal State Machine
The signal is a simple three-state machine. The key constraint: transitions are unidirectional. A signal cannot jump from RED to YELLOW or from YELLOW to GREEN. The phase controller triggers the GREEN transition; the signal handles the rest.
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with NotesFromSDE Premium.