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
| Entity | Responsibility | Key Attributes |
|---|---|---|
| ParkingLot | Owns floors and coordinates parking | identifier, floors |
| Floor | Groups slots on one level | levelIndex, slots |
| Slot | Holds at most one vehicle | identifier, sizeCategory, occupied, vehicleReference |
| Vehicle | Describes what is parked | identifier, licensePlate, sizeCategory |
| ParkingTicket | Proof of session | ticketCode, entryTimestamp, slotIdentifier |
| FeePolicy | Computes amount owed | rules 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
Slotinstances 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.Mutexper 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
Slotsubtype withSupplyPowerhook and pricing via extendedFeePolicy. - Multi-lot routing: facade over several
ParkingLotinstances 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?