Parking Lot System Design: Complete OOP Guide
Introduction#
The parking lot system design question is one of the most popular object-oriented design problems in software engineering interviews. It tests your ability to model real-world entities, define clean interfaces, and handle concurrency and business logic.
In this guide we will walk through the full design — from core classes to pricing strategies, sensor integration, and reporting.
Requirements#
Functional#
- Support multiple floors and zones (compact, regular, large, handicapped)
- Assign vehicles to appropriate spots based on size
- Issue tickets on entry and process payment on exit
- Track real-time capacity per floor and zone
- Support reservations
- Generate usage reports
Non-Functional#
- Handle concurrent entry and exit without double-booking spots
- Low latency at gates (under 100ms response)
- High availability for payment processing
Core Classes#
Vehicle#
from enum import Enum
class VehicleType(Enum):
MOTORCYCLE = 1
COMPACT = 2
REGULAR = 3
LARGE = 4
class Vehicle:
def __init__(self, license_plate: str, vehicle_type: VehicleType):
self.license_plate = license_plate
self.vehicle_type = vehicle_type
ParkingSpot#
class SpotStatus(Enum):
AVAILABLE = 1
OCCUPIED = 2
RESERVED = 3
OUT_OF_SERVICE = 4
class ParkingSpot:
def __init__(self, spot_id: str, floor: int, zone: str, spot_type: VehicleType):
self.spot_id = spot_id
self.floor = floor
self.zone = zone
self.spot_type = spot_type
self.status = SpotStatus.AVAILABLE
self.vehicle = None
def can_fit(self, vehicle: Vehicle) -> bool:
return vehicle.vehicle_type.value <= self.spot_type.value
def assign(self, vehicle: Vehicle):
self.vehicle = vehicle
self.status = SpotStatus.OCCUPIED
def release(self):
self.vehicle = None
self.status = SpotStatus.AVAILABLE
Ticket#
import time, uuid
class Ticket:
def __init__(self, vehicle: Vehicle, spot: ParkingSpot):
self.ticket_id = str(uuid.uuid4())
self.vehicle = vehicle
self.spot = spot
self.entry_time = time.time()
self.exit_time = None
self.amount_due = 0.0
ParkingLot (Singleton)#
class ParkingLot:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, name: str, floors: int):
self.name = name
self.floors = {} # floor_number -> list of ParkingSpot
self.active_tickets = {} # ticket_id -> Ticket
self.pricing = HourlyPricing()
def find_spot(self, vehicle: Vehicle) -> ParkingSpot:
for floor_spots in self.floors.values():
for spot in floor_spots:
if spot.status == SpotStatus.AVAILABLE and spot.can_fit(vehicle):
return spot
return None
def issue_ticket(self, vehicle: Vehicle) -> Ticket:
spot = self.find_spot(vehicle)
if not spot:
raise Exception("No available spot")
spot.assign(vehicle)
ticket = Ticket(vehicle, spot)
self.active_tickets[ticket.ticket_id] = ticket
return ticket
def process_exit(self, ticket_id: str) -> float:
ticket = self.active_tickets.pop(ticket_id)
ticket.exit_time = time.time()
ticket.amount_due = self.pricing.calculate(ticket)
ticket.spot.release()
return ticket.amount_due
Floor and Zone Management#
Each floor contains zones optimized for different vehicle types. A FloorManager keeps a count of available spots per zone so the system can quickly reject vehicles when capacity is full, avoiding a full scan.
class FloorManager:
def __init__(self, floor_number: int, spots: list):
self.floor_number = floor_number
self.spots = spots
def available_count(self, zone: str = None) -> int:
return sum(
1 for s in self.spots
if s.status == SpotStatus.AVAILABLE
and (zone is None or s.zone == zone)
)
Pricing Strategies#
Use the Strategy pattern so pricing logic is swappable.
class PricingStrategy:
def calculate(self, ticket: Ticket) -> float:
raise NotImplementedError
class HourlyPricing(PricingStrategy):
RATE = 5.0 # per hour
def calculate(self, ticket: Ticket) -> float:
hours = (ticket.exit_time - ticket.entry_time) / 3600
return round(hours * self.RATE, 2)
class FlatPricing(PricingStrategy):
FLAT_RATE = 20.0
def calculate(self, ticket: Ticket) -> float:
return self.FLAT_RATE
Sensor Integration#
Modern lots use sensors at each spot — ultrasonic or magnetic — that publish events to a message bus.
- Sensor publishes
{spot_id, occupied: true/false}to a message queue. - SpotService consumes the event and updates
ParkingSpot.status. - Display boards subscribe to capacity changes and refresh in real time.
This decoupled architecture lets the core system stay responsive regardless of sensor hardware.
Reservation System#
A reservation locks a spot for a future time window. The ReservationService checks for conflicts and transitions the spot to RESERVED status. If the driver does not arrive within a grace period (e.g., 15 minutes), the reservation expires and the spot returns to AVAILABLE.
Payment#
Payment is processed at exit. The flow:
- Scan ticket at exit gate.
- Calculate amount using the active
PricingStrategy. - Charge via payment gateway (credit card, mobile wallet, prepaid account).
- On success, open the exit gate barrier.
For resilience, use an idempotency key tied to the ticket ID so retries do not double-charge.
Capacity Tracking#
Maintain an in-memory counter per floor and zone, updated atomically on every assign/release. Expose a REST endpoint:
GET /api/capacity?floor=2&zone=compact
{ "total": 50, "available": 12 }
Display boards and mobile apps poll or subscribe via WebSocket.
Entry and Exit Gates#
Gates are modeled as state machines: CLOSED -> OPENING -> OPEN -> CLOSING -> CLOSED. Each gate controller communicates with the ParkingLot service over gRPC. Entry gates call issue_ticket; exit gates call process_exit.
Reporting#
An analytics pipeline ingests ticket events into a data warehouse. Common reports include:
- Occupancy rate by hour, day, and month
- Revenue broken down by zone and vehicle type
- Average duration of stay
- Peak hours heatmap
Summary#
| Component | Pattern / Tech |
|---|---|
| ParkingLot | Singleton |
| Pricing | Strategy |
| Sensors | Observer / Event Bus |
| Gates | State Machine / gRPC |
| Payment | Idempotent Gateway |
| Reporting | Event Sourcing / OLAP |
The parking lot system design is an excellent exercise in combining OOP fundamentals with real-world distributed systems thinking.
Build and practice system design problems interactively on codelit.io.
This is article #207 in the Codelit engineering blog series.
Try it on Codelit
Chaos Mode
Simulate node failures and watch cascading impact across your architecture
Related articles
Try these templates
Uber Real-Time Location System
Handles 5M+ GPS pings per second using H3 hexagonal geospatial indexing.
6 componentsE-Commerce Checkout System
Production checkout flow with Stripe payments, inventory management, and fraud detection.
11 componentsNotification System
Multi-channel notification platform with preferences, templating, and delivery tracking.
9 componentsBuild this architecture
Generate an interactive architecture for Parking Lot System Design in seconds.
Try it in Codelit →
Comments