THN Interview Prep

Design Parking Lot (LLD)

1. Requirements

  • Functional

    • Register a multi-level lot with slots tagged by vehicle size (compact, large, handicapped).
    • Park a vehicle on the nearest suitable free slot; reject when full or incompatible.
    • Unpark using ticket or slot identity; free the slot; compute fees by duration and vehicle type.
    • Query occupancy by floor and slot type for dashboards (optional in minimal scope).
  • Non-Functional

    • Concurrent arrivals must not double-assign the same slot (linearizable assignment).
    • Extensible pricing and slot discovery strategy without rewriting ParkingLot.
    • Slot lookup and assignment should target O(log n) or O(n) per floor with clear bounds.
  • Assumptions / Out of Scope

    • Single deployment process; no distributed lot spanning nodes.
    • Payment gateway integration stubbed; focus on domain and allocation correctness.

2. Core Entities

EntityResponsibilityKey Attributes
ParkingLotOwns floors and coordinates parkingidentifier, floors
FloorGroups slots on one levellevelIndex, slots
SlotHolds at most one vehicleidentifier, sizeCategory, occupied, vehicleReference
VehicleDescribes what is parkedidentifier, licensePlate, sizeCategory
ParkingTicketProof of sessionticketCode, entryTimestamp, slotIdentifier
FeePolicyComputes amount owedrules per vehicle size and time buckets

3. Class Diagram

Loading diagram…

4. State / Sequence Diagram (where relevant)

Loading diagram…

5. Design Patterns Applied

  • Strategy — Pluggable slot search (nearest-first vs smallest-fit). See Strategy pattern.
  • Factory — Build Slot instances by size category for consistent defaults. See Factory Method pattern.
  • Chain of Responsibility — Floors tried in order until a slot matches (optional extension).

6. Implementation

Go

package parkinglot

type SizeCategory int

type Vehicle struct {
    Identifier   string
    LicensePlate string
    Size         SizeCategory
}

type Slot struct {
    Identifier string
    Size       SizeCategory
    Occupied   bool
    VehicleRef *Vehicle
}

type Floor struct {
    LevelIndex int
    Slots      []*Slot
}

type ParkingLot struct {
    Floors []*Floor
}

func (lot *ParkingLot) Park(vehicle Vehicle) (ticketCode string, err error) { /* ... */ }
func (lot *ParkingLot) Leave(ticketCode string) (feeCents int64, err error) { /* ... */ }

JavaScript

class Vehicle {
  constructor({ identifier, licensePlate, sizeCategory }) {
    this.identifier = identifier;
    this.licensePlate = licensePlate;
    this.sizeCategory = sizeCategory;
  }
}

class Slot {
  constructor({ identifier, sizeCategory }) {
    this.identifier = identifier;
    this.sizeCategory = sizeCategory;
    this.occupied = false;
    this.vehicle = null;
  }
  occupy(vehicle) { /* ... */ }
  release() { /* ... */ }
}

class ParkingLot {
  constructor({ floors }) {
    this.floors = floors;
  }
  park(vehicle) { /* returns ticket id */ }
  leave(ticketCode) { /* returns fee */ }
}

7. Concurrency / Thread Safety

  • Collisions: Two threads parking the same size may race for the last compatible slot on a floor.
  • Granularity: Hold a short-lived mutex per floor during search-and-occupy, or per-slot try-lock after candidate selection; avoid one global lock for the whole lot.
  • Go: sync.Mutex per floor; document lock order if also locking lot-level indexes.
  • JavaScript: Serialize parking API with a promise queue per floor or use atomic compare-and-swap in a shared store if multi-worker.

8. Extensibility & Followups

  • EV charging bays as Slot subtype with SupplyPower hook and pricing via extended FeePolicy.
  • Multi-lot routing: facade over several ParkingLot instances with external directory service.
  • Reservations: add ticket state machine (requested, confirmed, expired) before occupy.
  • Edge cases: ticket replay, clock skew on fee calculation, abandoning vehicle mid-payment.

Last updated on

Spotted something unclear or wrong on this page?

On this page