🇮🇳
🇮🇳
Republic Day Special Offer!Get 20% OFF on all courses
Enroll Now
P
Prakalpana
📚Learn
Code Your Future
System Design⏱️ 20 min read📅 Jan 8

LLD: Design Parking Lot System - Complete Object-Oriented Design

RS
Rahul SharmaSenior Engineer at Amazon
📑 Contents (12 sections)

📌Problem Statement

Design a parking lot system with multiple floors, different vehicle types, and automated ticketing.

📌Requirements

Functional

  • Multiple floors with parking spots
  • Different spot sizes: Motorcycle, Compact, Large
  • Entry/exit points with ticketing
  • Hourly rate calculation
  • Real-time availability display
  • Constraints

  • Motorcycle can park in any spot
  • Compact car in Compact or Large
  • Large vehicle only in Large spot
  • 📌Class Design

    Core Classes

    public enum VehicleType {
    MOTORCYCLE, CAR, TRUCK
    }
    public enum SpotType {
    MOTORCYCLE, COMPACT, LARGE
    }
    public enum TicketStatus {
    ACTIVE, PAID, LOST
    }

    Vehicle Class

    public abstract class Vehicle {
    private String licensePlate;
    private VehicleType type;
    public Vehicle(String licensePlate, VehicleType type) {
    this.licensePlate = licensePlate;
    this.type = type;
    }
    public abstract boolean canFitIn(SpotType spotType);
    }
    public class Car extends Vehicle {
    public Car(String licensePlate) {
    super(licensePlate, VehicleType.CAR);
    }
    public boolean canFitIn(SpotType spotType) {
    return spotType == SpotType.COMPACT || spotType == SpotType.LARGE;
    }
    }
    public class Motorcycle extends Vehicle {
    public Motorcycle(String licensePlate) {
    super(licensePlate, VehicleType.MOTORCYCLE);
    }
    public boolean canFitIn(SpotType spotType) {
    return true;
    }
    }
    public class Truck extends Vehicle {
    public Truck(String licensePlate) {
    super(licensePlate, VehicleType.TRUCK);
    }
    public boolean canFitIn(SpotType spotType) {
    return spotType == SpotType.LARGE;
    }
    }

    ParkingSpot Class

    public class ParkingSpot {
    private String spotId;
    private SpotType type;
    private Vehicle vehicle;
    private int floor;
    public ParkingSpot(String spotId, SpotType type, int floor) {
    this.spotId = spotId;
    this.type = type;
    this.floor = floor;
    }
    public boolean isAvailable() {
    return vehicle == null;
    }
    public boolean canFit(Vehicle vehicle) {
    return isAvailable() && vehicle.canFitIn(type);
    }
    public void park(Vehicle vehicle) {
    if (!canFit(vehicle)) {
    throw new IllegalStateException("Cannot park here");
    }
    this.vehicle = vehicle;
    }
    public Vehicle unpark() {
    Vehicle v = this.vehicle;
    this.vehicle = null;
    return v;
    }
    }

    Ticket and Payment

    public class Ticket {
    private String ticketId;
    private Vehicle vehicle;
    private ParkingSpot spot;
    private LocalDateTime entryTime;
    private LocalDateTime exitTime;
    private TicketStatus status;
    private double amount;
    public Ticket(Vehicle vehicle, ParkingSpot spot) {
    this.ticketId = UUID.randomUUID().toString();
    this.vehicle = vehicle;
    this.spot = spot;
    this.entryTime = LocalDateTime.now();
    this.status = TicketStatus.ACTIVE;
    }
    public double calculateFee(PricingStrategy strategy) {
    long hours = ChronoUnit.HOURS.between(entryTime, LocalDateTime.now());
    return strategy.calculate(hours, vehicle.getType());
    }
    }
    public interface PricingStrategy {
    double calculate(long hours, VehicleType type);
    }
    public class HourlyPricing implements PricingStrategy {
    private Map<VehicleType, Double> rates;
    public double calculate(long hours, VehicleType type) {
    return Math.max(1, hours) * rates.get(type);
    }
    }

    ParkingLot - Main Class

    public class ParkingLot {
    private static ParkingLot instance;
    private List<ParkingFloor> floors;
    private Map<String, Ticket> activeTickets;
    private PricingStrategy pricingStrategy;
    private ParkingLot() {
    floors = new ArrayList<>();
    activeTickets = new ConcurrentHashMap<>();
    }
    public static synchronized ParkingLot getInstance() {
    if (instance == null) {
    instance = new ParkingLot();
    }
    return instance;
    }
    public Ticket parkVehicle(Vehicle vehicle) {
    ParkingSpot spot = findAvailableSpot(vehicle);
    if (spot == null) {
    throw new ParkingFullException("No spot available");
    }
    spot.park(vehicle);
    Ticket ticket = new Ticket(vehicle, spot);
    activeTickets.put(ticket.getTicketId(), ticket);
    return ticket;
    }
    public double unparkVehicle(String ticketId) {
    Ticket ticket = activeTickets.get(ticketId);
    if (ticket == null) {
    throw new InvalidTicketException("Ticket not found");
    }
    double fee = ticket.calculateFee(pricingStrategy);
    ticket.getSpot().unpark();
    activeTickets.remove(ticketId);
    return fee;
    }
    private ParkingSpot findAvailableSpot(Vehicle vehicle) {
    for (ParkingFloor floor : floors) {
    ParkingSpot spot = floor.findSpot(vehicle);
    if (spot != null) return spot;
    }
    return null;
    }
    }

    📌Design Patterns Used

  • 1Singleton - ParkingLot instance
  • 2Strategy - PricingStrategy for flexible pricing
  • 3Factory - Could add VehicleFactory for creating vehicles
  • 📌Interview Tips

  • Start with requirements clarification
  • Draw class diagram first
  • Explain SOLID principles applied
  • Discuss extensibility (new vehicle types, pricing models)
  • Handle edge cases (lost ticket, full parking)
  • This is a classic LLD question asked at Amazon, Google, and Flipkart.

    RS

    Written by

    Rahul Sharma

    Senior Engineer at Amazon

    🚀 Master System Design

    Join 500+ developers

    Explore Courses →
    Chat on WhatsApp