Low-Level Design Tutorial 0/42 lessons ~6 min read Lesson 31

    Parking Lot System

    The parking lot is the most common LLD interview question.

    Course progress0%
    Focus
    9 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    The parking lot is the most common LLD interview question. It tests entity modeling, spot allocation, ticketing, fee calculation, and extension to multiple vehicle types or floors.

    A strong answer defines Vehicle, ParkingSpot, ParkingLot, Ticket, and optionally PaymentService — with clear park/unpark flows and thread safety if multiple entry gates exist.

    Start with requirements, draw classes, walk park sequence, then handle full lot and fee edge cases.

    Understanding the topic

    Key concepts

    • Entities: ParkingLot, ParkingSpot, Vehicle, Ticket, EntryPanel.
    • Spot types: compact, large, handicapped, electric.
    • Allocation: nearest free spot or level preference.
    • Ticket links vehicle, spot, entry time.
    • Fee on exit based on duration and vehicle rate.
    • Concurrency: synchronized lot or lock per floor.
    text
    classDiagram
    class ParkingLot {
    -List~Spot~ spots
    +park(Vehicle) Ticket
    +unpark(Ticket) void
    }
    class Vehicle
    class ParkingSpot
    class Ticket
    ParkingLot --> ParkingSpot
    ParkingLot --> Ticket
    Vehicle --> ParkingSpot

    Step-by-step explanation

    1. Vehicle arrives; system finds compatible free spot.
    2. Occupy spot; issue Ticket with unique id and timestamp.
    3. On exit, validate ticket, compute fee, release spot.
    4. Handle full lot exception gracefully.
    5. Support multiple entrances sharing one lot state.
    6. Extend with pricing strategy per vehicle type.

    Informative example

    Complete parking lot core with Vehicle, ParkingSpot, Ticket, and ParkingLot:

    java
    public enum SpotType { COMPACT, LARGE, BIKE }
    public sealed interface Vehicle permits CarVehicle, TruckVehicle, BikeVehicle {
    String plate();
    SpotType requiredSpot();
    }
    public record CarVehicle(String plate) implements Vehicle {
    public SpotType requiredSpot() { return SpotType.COMPACT; }
    }
    public record TruckVehicle(String plate) implements Vehicle {
    public SpotType requiredSpot() { return SpotType.LARGE; }
    }
    public record BikeVehicle(String plate) implements Vehicle {
    public SpotType requiredSpot() { return SpotType.BIKE; }
    }
    public final class ParkingSpot {
    private final int id;
    private final SpotType type;
    private Vehicle occupiedBy;
    public ParkingSpot(int id, SpotType type) {
    this.id = id;
    this.type = type;
    }
    public boolean isFree() { return occupiedBy == null; }
    public boolean supports(SpotType t) { return type == t; }
    public synchronized void park(Vehicle v) {
    if (!isFree()) throw new IllegalStateException("occupied");
    occupiedBy = v;
    }
    public synchronized void release() { occupiedBy = null; }
    }
    public final class Ticket {
    private final String id;
    private final ParkingSpot spot;
    private final Vehicle vehicle;
    private final Instant entry;
    private Ticket(ParkingSpot spot, Vehicle vehicle) {
    this.id = UUID.randomUUID().toString();
    this.spot = spot;
    this.vehicle = vehicle;
    this.entry = Instant.now();
    }
    public static Ticket issue(ParkingSpot spot, Vehicle vehicle) {
    return new Ticket(spot, vehicle);
    }
    public String id() { return id; }
    public ParkingSpot spot() { return spot; }
    public Instant entry() { return entry; }
    public Money calculateFee(Money hourlyRate) {
    long hours = (long) Math.ceil(Duration.between(entry, Instant.now()).toMinutes() / 60.0);
    return hourlyRate.multiply(Math.max(1, hours));
    }
    }
    public final class ParkingLot {
    private final List<ParkingSpot> spots = new ArrayList<>();
    private final Map<String, Ticket> active = new ConcurrentHashMap<>();
    public void addSpot(ParkingSpot spot) { spots.add(spot); }
    public synchronized Ticket park(Vehicle vehicle) {
    ParkingSpot spot = spots.stream()
    .filter(s -> s.isFree() && s.supports(vehicle.requiredSpot()))
    .findFirst()
    .orElseThrow(() -> new IllegalStateException("full"));
    spot.park(vehicle);
    Ticket ticket = Ticket.issue(spot, vehicle);
    active.put(ticket.id(), ticket);
    return ticket;
    }
    public synchronized Money unpark(String ticketId) {
    Ticket ticket = active.remove(ticketId);
    if (ticket == null) throw new IllegalArgumentException("invalid ticket");
    Money fee = ticket.calculateFee(Money.of(5));
    ticket.spot().release();
    return fee;
    }
    }

    Discuss synchronized park/unpark vs ReadWriteLock for read-heavy monitoring extensions.

    Real-world use

    Real-world applications

    • Standard SDE2 LLD interview warm-up.
    • Practice class + sequence diagram alignment.
    • Concurrency and fee policy extensions.

    Best practices

    • Model ticket as first-class entity with lifecycle.
    • Separate spot finder strategy if multiple floors.
    • Use vehicle.requiredSpot() not instanceof chains.
    • Idempotent unpark handling for duplicate scans.
    • Immutable Money for fees.

    Common mistakes

    • No ticket object — only spot reference lost on exit.
    • Same spot assigned twice without occupy check.
    • Fee logic duplicated in panel and central system.
    • Forgetting vehicle-to-spot type matching.

    Advanced interview questions

    Q1BeginnerCore classes for parking lot?
    ParkingLot, ParkingSpot, Vehicle, Ticket; optional EntryGate and PaymentService.
    Q2BeginnerHow find spot for truck?
    Filter free spots where supports(LARGE) or type matches vehicle.requiredSpot().
    Q3IntermediateMultiple entry gates thread safety?
    Synchronize park on lot or use concurrent spot reservation with compare-and-set.
    Q4IntermediateAdd electric charging spots?
    SpotType.EV, ChargingSpot subclass or flag; EVehicle interface requiring EV spot.
    Q5AdvancedDesign multi-floor parking with display panel.
    Floor composes spots; FloorDirectory finds nearest; DisplayObserver implements Observer on lot occupancy.

    Summary

    Parking lot = vehicle, spot, ticket, lot orchestrator. Match spot type to vehicle requirements. Ticket captures entry time for fee on exit. Handle full lot and invalid ticket paths. Extend with floors, pricing, and concurrency as asked.

    Ready to mark this lesson complete?Track your journey across the entire course.