Skip to content

Parking Lot#

Problem statement (interviewer prompt)

Design a parking lot system: model the lot, spots of different sizes (motorcycle / car / van), the entry / exit gates, ticketing, real-time availability, pricing by duration, and reservations. Focus on the OO class model and the state transitions.

classDiagram
  class ParkingLot {
    +levels : List~Level~
    +park(v: Vehicle) Ticket
    +unpark(t: Ticket) double
  }
  class Level {
    +slots : List~Slot~
    +findFreeSlot(v) Slot
  }
  class Slot {
    +id
    +type : SlotType
    +occupied : boolean
  }
  class Vehicle {
    <<abstract>>
    +regNo
    +type : VehicleType
  }
  ParkingLot "1" *-- "many" Level
  Level "1" *-- "many" Slot
  Vehicle <|-- Car
  Vehicle <|-- Bike
  Vehicle <|-- Truck
classDiagram
  direction TB

  class ParkingLot {
    -levels: List~Level~
    -ticketRepo: TicketRepo
    -strategy: AllocationStrategy
    -paymentSvc: PaymentService
    +park(v: Vehicle) Ticket
    +unpark(t: Ticket) Receipt
    +findSlot(v: Vehicle) Slot
  }

  class Level {
    -slots: List~Slot~
    -id: int
    +freeSlots(type) List~Slot~
  }

  class Slot {
    -id: String
    -type: SlotType
    -occupied: boolean
    +occupy(v: Vehicle)
    +release()
  }

  class Vehicle {
    <<abstract>>
    +regNo: String
    +type(): VehicleType
  }
  class Car
  class Bike
  class Truck
  class EV {
    +chargingPort: boolean
  }

  class Ticket {
    +id: String
    +entryTs: Instant
    +slot: Slot
    +vehicle: Vehicle
  }

  class Receipt {
    +ticketId: String
    +exitTs: Instant
    +duration
    +amount
    +paymentRef
  }

  class AllocationStrategy {
    <<interface>>
    +pick(slots, vehicle) Slot
  }
  class NearestFirst
  class CompactSlot
  class ByVehicleType

  class PricingPolicy {
    <<interface>>
    +cost(duration, vehicle) Money
  }
  class FlatHourly
  class PeakOffPeak
  class DayPass

  class PaymentService {
    +charge(amount, method) PaymentRef
  }

  class GateController {
    -entryGates
    -exitGates
    +open(g)
    +close(g)
  }

  class DisplayBoard {
    +update(level, free)
  }

  class TicketRepo {
    <<interface>>
    +save(t)
    +findById(id) Ticket
  }

  ParkingLot "1" *-- "many" Level
  Level "1" *-- "many" Slot
  Vehicle <|-- Car
  Vehicle <|-- Bike
  Vehicle <|-- Truck
  Vehicle <|-- EV
  ParkingLot --> AllocationStrategy
  AllocationStrategy <|.. NearestFirst
  AllocationStrategy <|.. CompactSlot
  AllocationStrategy <|.. ByVehicleType
  ParkingLot --> PricingPolicy
  PricingPolicy <|.. FlatHourly
  PricingPolicy <|.. PeakOffPeak
  PricingPolicy <|.. DayPass
  ParkingLot --> PaymentService
  ParkingLot --> TicketRepo
  ParkingLot --> GateController
  ParkingLot --> DisplayBoard
  Ticket --> Slot
  Ticket --> Vehicle

Design notes#

  • Strategy pattern for allocation and pricing (swap without code change).
  • Repository pattern hides DB; tests use in-memory.
  • Observer pattern for DisplayBoard (subscribes to slot changes).
  • State on Slot prevents double-occupy; CAS in repo.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
LLD Testing strategy pyramid, doubles, TDD, contracts testing-strategy
LLD Behavioural patterns Strategy, Observer, State, Command, Chain behavioral-patterns
LLD Concurrency primitives mutex, semaphore, RW lock, atomic, CAS concurrency-primitives

Quick reference#

Functional#

  • Issue tickets on entry.
  • Find free slot per vehicle type / EV.
  • Compute fee, accept payment, allow exit.
  • Display free-count per level.

Non-functional#

  • 99.9% uptime; offline-safe (gates can fail closed safely).
  • Concurrent entries handled.
  • Audit log of every entry/exit.

API (services)#

  • Ticket park(Vehicle)
  • Receipt unpark(ticketId)
  • int freeSlots(level, type)

Patterns#

  • Strategy: AllocationStrategy, PricingPolicy.
  • Repository: tickets, slots.
  • Observer: DisplayBoard.
  • Factory: VehicleFactory by regNo / declared type.
  • State: SlotState (FREE / OCCUPIED / RESERVED / OUT_OF_SERVICE).

Trade-offs#

  • Flat hourly simplest; dynamic pricing harder to explain to users.
  • Pre-reserved slots for monthly passes vs first-come first-serve.

Refs#

  • Common LLD interview templates (Grokking the Object Oriented Design Interview).
  • Refactoring guru patterns.

FAQ#

How do you model vehicles in a parking lot?#

Use an abstract Vehicle class with subclasses Motorcycle, Car, Van, and Truck; each declares the spot sizes it fits so the allocation strategy can match supply to demand.

How is a spot allocated efficiently?#

Keep a priority queue or per-size free list per level. Allocation polls the queue for the right size, marks the spot OCCUPIED, and emits a Ticket in O(log N) or O(1).

How does parking pricing work?#

Strategy pattern: a PricingStrategy computes fee from entry time, exit time, and vehicle type. Hourly, slab-based, or flat-rate strategies plug into the same exit flow.

How do you handle concurrent entries at the gate?#

Per-level locks or atomic compare-and-set on the free list ensure two vehicles cannot claim the same spot. The DB-backed version uses SELECT FOR UPDATE on the spot row.

What classes belong in a parking lot LLD?#

ParkingLot, Level, ParkingSpot (with size enum), Vehicle hierarchy, Ticket, Payment, PricingStrategy, EntryGate, and ExitGate cover the core domain.

Video walkthrough

Design Parking Lot: LLD, UML, Concurrency & Code Explained : via Concept && Coding