LLD Hub
lldoopstrategy-patternstate-machine

Parking Lot Low Level Design — Complete LLD Interview Guide

Complete Parking Lot LLD solution — class diagram, Strategy pattern for pricing, Java code, and what interviewers look for at Amazon, Flipkart. 1500+ word guide.

1 April 2025·8 min read

Practice this problem

Parking Lot System — get AI-scored feedback on your solution

Solve it →

The Parking Lot system is one of the most frequently asked Low Level Design problems in software engineering interviews. Companies like Amazon, Flipkart, Microsoft, and Uber use this problem to evaluate your understanding of Object-Oriented Design, SOLID principles, and the Strategy design pattern. In this complete parking lot LLD guide, we go from requirements to class diagram to working Java code.

Why Interviewers Ask the Parking Lot LLD Problem

The Parking Lot problem is deceptively simple on the surface but reveals a lot about how you think. Interviewers want to see:

  • Can you identify the right entities without over-engineering?
  • Do you apply Single Responsibility Principle — each class does one thing?
  • Can you use the Strategy pattern for extensible pricing?
  • Do you think about edge cases like concurrent access and finding the nearest slot?
  • Can you model enums cleanly for vehicle types and slot sizes?

Functional Requirements

  • Support multiple floors, each with a configurable number of slots
  • Three vehicle types: Bike, Car, Truck — each requires a different slot size
  • Allocate the nearest available slot to an incoming vehicle
  • Issue a ticket on entry with timestamp and slot details
  • Calculate parking fee on exit based on duration and vehicle type
  • Free up the slot when a vehicle exits
  • Display available slot count per floor and vehicle type

Non-Functional Requirements

  • Concurrent entry and exit must be handled safely — no double-allocation of slots
  • Adding a new vehicle type or pricing strategy must not require modifying existing classes (OCP)
  • Slot search should be O(1) or O(floors) using data structures, not a full O(n) scan

Core Entities — Parking Lot LLD Class Design

  • ParkingLot — singleton, manages all floors, entry and exit
  • Floor — contains slots, tracks availability per slot type
  • Slot — type (SMALL/MEDIUM/LARGE), number, floor, occupied status
  • Vehicle — abstract base; Bike, Car, Truck extend it
  • Ticket — issued at entry: vehicle, slot, entry time
  • PricingStrategy — interface; HourlyPricing, FlatRatePricing implement it
  • Payment — amount, method, timestamp
  • EntrancePanel / ExitPanel — hardware interface abstractions

Text-Based Class Diagram

ParkingLot (Singleton)
+-- floors: List<Floor>
+-- pricingStrategy: PricingStrategy
+-- activeTickets: Map<String, Ticket>
+-- parkVehicle(vehicle): Ticket
+-- unparkVehicle(ticketId): Payment

Floor
+-- floorNumber: int
+-- slots: List<Slot>
+-- getNearestAvailableSlot(type): Slot

Slot
+-- slotNumber: int
+-- type: SlotType (SMALL / MEDIUM / LARGE)
+-- isOccupied: boolean
+-- assignVehicle() / free()

Vehicle (abstract)
+-- licensePlate: String
+-- type: VehicleType
Bike / Car / Truck extend Vehicle

Ticket
+-- ticketId: String
+-- vehicle: Vehicle
+-- slot: Slot
+-- entryTime: LocalDateTime

PricingStrategy (interface)
+-- calculateFee(ticket, exitTime): double

HourlyPricing implements PricingStrategy
FlatRatePricing implements PricingStrategy

Strategy Pattern for Pricing — Java

public interface PricingStrategy {
    double calculateFee(Ticket ticket, LocalDateTime exitTime);
}

public class HourlyPricing implements PricingStrategy {
    private final Map<VehicleType, Double> ratePerHour = new EnumMap<>(VehicleType.class);

    public HourlyPricing() {
        ratePerHour.put(VehicleType.BIKE,  10.0);
        ratePerHour.put(VehicleType.CAR,   20.0);
        ratePerHour.put(VehicleType.TRUCK, 50.0);
    }

    @Override
    public double calculateFee(Ticket ticket, LocalDateTime exitTime) {
        long hours = ChronoUnit.HOURS.between(ticket.getEntryTime(), exitTime);
        hours = Math.max(hours, 1); // minimum 1 hour
        return hours * ratePerHour.get(ticket.getVehicle().getType());
    }
}

ParkingLot Core Logic

public class ParkingLot {
    private static ParkingLot instance;
    private final List<Floor> floors;
    private final PricingStrategy pricingStrategy;
    private final Map<String, Ticket> activeTickets = new ConcurrentHashMap<>();

    private ParkingLot(List<Floor> floors, PricingStrategy strategy) {
        this.floors = floors;
        this.pricingStrategy = strategy;
    }

    public static synchronized ParkingLot getInstance(List<Floor> floors, PricingStrategy strategy) {
        if (instance == null) instance = new ParkingLot(floors, strategy);
        return instance;
    }

    public Ticket parkVehicle(Vehicle vehicle) {
        SlotType required = SlotType.forVehicle(vehicle.getType());
        for (Floor floor : floors) {
            Slot slot = floor.getNearestAvailableSlot(required);
            if (slot != null) {
                slot.assignVehicle(vehicle);
                Ticket ticket = new Ticket(UUID.randomUUID().toString(),
                                           vehicle, slot, LocalDateTime.now());
                activeTickets.put(ticket.getTicketId(), ticket);
                return ticket;
            }
        }
        throw new ParkingFullException("No slot available for " + vehicle.getType());
    }

    public Payment unparkVehicle(String ticketId) {
        Ticket ticket = activeTickets.remove(ticketId);
        if (ticket == null) throw new InvalidTicketException(ticketId);
        LocalDateTime exitTime = LocalDateTime.now();
        double fee = pricingStrategy.calculateFee(ticket, exitTime);
        ticket.getSlot().free();
        return new Payment(fee, PaymentMethod.CASH, exitTime);
    }
}

Key Design Decisions

  • Singleton ParkingLot: Only one instance should exist per system. Use double-checked locking or an enum-based singleton for thread safety in a multi-threaded environment.
  • Strategy over inheritance for pricing: Subclassing ParkingLot per pricing model violates SRP. With Strategy, adding a weekend rate or EV discount is a new class — zero changes to existing code.
  • ConcurrentHashMap for active tickets: Multiple entry and exit lanes run in parallel. ConcurrentHashMap provides thread-safe put/remove without a global lock.
  • SlotType maps to VehicleType: Bike → SMALL, Car → MEDIUM, Truck → LARGE. Keep this mapping in one place — a static factory method on SlotType — not scattered across callers.

Common Follow-Up Questions

  • "How do you handle two vehicles racing for the same slot?" — SynchronizegetNearestAvailableSlot + assignVehicle at the floor level, or use an atomic CAS operation on the slot's occupied flag.
  • "How do you support EV charging slots?" — Add a SlotFeature enum (REGULAR, EV_CHARGING, HANDICAP). Slot gets a feature field. Search filters by feature when needed.
  • "How do you find the nearest slot efficiently?" — Each floor maintains a sorted set or min-heap of available slot numbers per type. getNearestAvailableSlot is O(log n).
  • "How would you add monthly subscription support?" — Vehicle gets an optional Subscription. PricingStrategy checks for an active subscription before calculating the hourly fee.

FAQ — Parking Lot Low Level Design

What design patterns are used in Parking Lot LLD?

The primary patterns are Strategy (swap pricing algorithms without changing ParkingLot),Singleton (one ParkingLot instance), and Factory (create Vehicle objects from a type string). The Observer pattern is optionally used to update a display board when slot availability changes.

What is the class diagram for a Parking Lot system?

Core classes: ParkingLot (singleton) → Floor → Slot, Vehicle (abstract) → Bike/Car/Truck, Ticket (links Vehicle + Slot + entry time), PricingStrategy → HourlyPricing/FlatRatePricing, Payment. ParkingLot has many Floors; each Floor has many Slots.

How do you handle concurrent parking in Parking Lot LLD?

Use ConcurrentHashMap for active tickets and synchronize slot assignment at the floor level. Alternatively, use an atomic boolean in Slot with compareAndSet so only one thread can mark a slot occupied at a time.

Is the Parking Lot problem easy or hard?

Beginner to intermediate. Entities are clear, the Strategy pattern is textbook, and the concurrency requirement adds depth. It is the best first LLD problem because it covers fundamentals — entities, relationships, a design pattern, and edge cases — without overwhelming complexity.

Ready to practice?

Submit your solution and get AI-scored feedback on OOP, SOLID principles, design patterns, and code quality.

Solve Parking Lot System