Bird
Raised Fist0

Parking Lot System

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
๐ŸŽฏ
Parking Lot System Design with Spot Types, Entry/Exit, and Pricing
40 min ยท medium
medium

Design a parking lot system with 5 levels, each having multiple spot types (compact, large, handicapped, electric). The lot has 4 entry gates and 4 exit gates. Pricing varies by spot type and duration. The system must support concurrent vehicle entry and exit, track spot availability, and allow extensibility for new vehicle and spot types.

  • The parking lot has 5 levels with multiple spot types per level.
  • There are 4 entry gates and 4 exit gates operating concurrently.
  • Pricing depends on spot type and parking duration.
  • Vehicles can be motorcycles, cars, or trucks, each requiring different spot types.
  • The system must prevent race conditions when multiple vehicles park or leave simultaneously.
  • Spot availability must be updated atomically to avoid double-booking.
๐Ÿ“‹
Guided Steps
1/5
Step 1
Define Vehicle and Spot Types
Design the class hierarchy for vehicles and parking spots, considering different types and shared attributes.
๐Ÿ’ก Hint
Use abstract classes for entities with shared instance state; use enums for fixed types to leverage compile-time safety.
abstract class Vehicle with licensePlate and VehicleType enum fields to hold instance state and ensure type safety; VehicleType as enum for compile-time safety and exhaustive switch.
Mid: Defines abstract Vehicle class and concrete subclasses for each vehicle type; Senior: Explains why interface can't hold instance state and how enum prevents runtime typo bugs and enables exhaustive switch checking.
Step 2
Design Parking Spot and Level Management
Model parking spots with their types and availability status, and design how levels manage collections of spots.
๐Ÿ’ก Hint
Use volatile boolean isAvailable in ParkingSpot to ensure visibility across threads; Level aggregates ParkingSpot instances with lifecycle ownership.
volatile boolean isAvailable in ParkingSpot to guarantee visibility of spot status changes across threads; Level uses composition to own ParkingSpot instances and manage lifecycle tightly.
Mid: Uses composition for Level-ParkingSpot relationship; Senior: Explains volatile visibility guarantees and how stale reads cause double-booking.
Step 3
Implement Thread-Safe Parking and Unparking
Design methods to park and unpark vehicles ensuring atomic check-and-set of spot availability under concurrent access.
๐Ÿ’ก Hint
Use synchronized methods parkVehicle(Vehicle v) and unparkVehicle(Vehicle v) to atomically check and update spot availability, preventing race conditions.
public synchronized boolean parkVehicle(Vehicle v) to atomically check isAvailable and set to occupied; prevents race condition where two threads park simultaneously.
Mid: Uses synchronized methods for parking and unparking; Senior: Traces thread interleaving showing how synchronized prevents two threads from seeing isAvailable=true simultaneously.
Step 4
Design Entry and Exit Gates with Concurrency
Model entry and exit gates that handle vehicle flow concurrently and update parking lot state safely.
๐Ÿ’ก Hint
EntryGate and ExitGate use association with ParkingLot; methods handling vehicle entry/exit synchronize on ParkingLot instance to update shared state.
EntryGate and ExitGate hold references (association) to ParkingLot; synchronized methods on ParkingLot ensure thread-safe updates during vehicle entry and exit.
Mid: Uses association for gates to ParkingLot; Senior: Explains synchronized on ParkingLot methods prevents inconsistent spot availability updates.
Step 5
Implement Pricing Strategy per Spot Type
Design a pricing mechanism that calculates fees based on spot type and parking duration, allowing easy extension for new pricing rules.
๐Ÿ’ก Hint
Use Strategy pattern with PricingStrategy interface and concrete implementations per spot type; PricingStrategy is an interface because it defines behavior without state.
PricingStrategy interface defines calculateFee(long duration); concrete classes implement pricing per spot type; interface used because no shared instance state is needed.
Mid: Uses Strategy pattern for pricing; Senior: Explains interface used for behavior abstraction without state, enabling open-closed principle and easy extensibility.
๐Ÿ”Œ
API Design Challenge
Design APIs for vehicle entry, exit, spot allocation, and pricing calculation that support concurrency and extensibility.
  • Use synchronized or lock-based methods to ensure atomic updates to spot availability.
  • Design APIs to accept vehicle type and duration parameters to determine spot allocation and pricing.
  • Use interfaces and enums to allow easy extension for new vehicle and spot types without breaking existing APIs.
๐Ÿ“Š
Scoring Rubric
โ–ผ Show
Must Have - 60%
  • abstract class Vehicle with instance state and VehicleType enum
  • volatile boolean isAvailable in ParkingSpot for visibility
  • synchronized parkVehicle and unparkVehicle methods to prevent race conditions
  • EntryGate and ExitGate associations with ParkingLot and synchronized updates
  • PricingStrategy interface for pricing behavior abstraction
Good to Have - 30%
  • Composition relationship between Level and ParkingSpot with lifecycle ownership
  • Strategy pattern usage for pricing extensibility
  • Enum usage for SpotType and VehicleType to avoid runtime bugs
  • Explanation of thread interleaving causing race conditions without synchronization
  • Singleton pattern with volatile instance and double-checked locking for ParkingLot
Bonus - 10%
  • Detailed concurrency scenario tracing for parking and unparking
  • Extensibility for new vehicle and spot types without modifying existing code
  • Use of Java-specific concurrency constructs like volatile and synchronized explained
  • Clear SOLID principle references in design decisions
  • Lifecycle ownership explanations for composition vs association
โœ…
Model Answer
โ–ผ Reveal

    • abstract class Vehicle with licensePlate and VehicleType enum to hold instance state and ensure type safety.
    • enum SpotType and VehicleType to prevent runtime typo bugs and enable exhaustive switch statements.
    • ParkingSpot with volatile boolean isAvailable to guarantee visibility of availability changes across threads.
    • Level class uses composition to own ParkingSpot instances, managing lifecycle tightly.
    • synchronized methods parkVehicle(Vehicle v) and unparkVehicle(Vehicle v) to atomically check and update spot availability, preventing race conditions.
    • EntryGate and ExitGate hold associations to ParkingLot; synchronized methods on ParkingLot ensure thread-safe vehicle entry and exit.
    • PricingStrategy interface with concrete implementations per spot type to follow open-closed principle and separate pricing behavior.
    • Use of Strategy pattern for pricing to allow extensibility without modifying existing classes.
    • Double-checked locking with volatile singleton instance for ParkingLot (if singleton used) to prevent partially constructed object visibility.
    • Clear separation of concerns: Vehicle hierarchy, Spot management, Gate operations, and Pricing logic.

    Practice

    (1/5)
    1. A class provides a createIterator() method that returns an object allowing traversal over its elements without exposing its internal data structure. Which design pattern is being applied and why is this the correct choice?
    easy
    A. Factory Method pattern, because it encapsulates object creation logic.
    B. Decorator pattern, because it adds traversal behavior dynamically.
    C. Iterator pattern, because it separates traversal logic from the collection's internal structure.
    D. Composite pattern, because it treats individual and composite objects uniformly.

    Solution

    1. Step 1: Identify the role of createIterator()

      This method returns an object that allows clients to traverse elements without exposing the collection's internal representation, which is the core intent of the Iterator pattern.
    2. Step 2: Eliminate other patterns

      Factory Method focuses on object creation, Decorator adds responsibilities dynamically, and Composite manages tree structures. None focus on traversal abstraction.
    3. Final Answer:

      Option C -> Option C
    4. Quick Check:

      Iterator separates traversal from collection internals [check]
    Hint: Iterator hides structure, exposes traversal [check]
    Common Mistakes:
    2. In designing a Vehicle abstraction, should it be an abstract class or an interface if it needs to hold state like speed and fuelLevel? Why?
    easy
    A. Interface, because Java 8+ interfaces can have default methods and fields.
    B. Interface, because it allows multiple inheritance and enforces behavior contracts.
    C. Abstract class, because it can hold shared state and provide default behavior implementations.
    D. Abstract class, because it prevents any subclass from overriding methods.

    Solution

    1. Step 1: Analyze state and behavior requirements

      Since Vehicle needs to hold mutable state like speed and fuelLevel, it requires fields and possibly default implementations that manage this state.
    2. Step 2: Compare abstract class vs interface capabilities

      Abstract classes can hold instance variables and provide default method implementations that access state. Interfaces cannot hold instance state (only constants) and default methods cannot manage mutable state effectively.
    3. Final Answer:

      Option C -> Option C
    4. Quick Check:

      Stateful abstraction -> abstract class, not interface [check]
    Hint: Stateful abstraction needs abstract class, not interface [check]
    Common Mistakes:
    3. The brokerage system currently calculates fees using a FeeCalculator class. To add a new WeekendFeeStrategy without modifying existing code, which SOLID principle applies and what is the minimum change required?
    medium
    A. Open/Closed Principle: Create a new WeekendFeeStrategy class implementing FeeStrategy interface; FeeCalculator uses polymorphism.
    B. Single Responsibility Principle: Modify FeeCalculator to handle weekend fees explicitly.
    C. Dependency Inversion Principle: Inject concrete WeekendFeeStrategy directly into FeeCalculator constructor.
    D. Liskov Substitution Principle: Replace FeeCalculator with WeekendFeeCalculator subclass overriding fee logic.

    Solution

    1. Step 1: Identify the SOLID principle for extensibility

      Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
    2. Step 2: How to apply OCP here

      Create a new class WeekendFeeStrategy implementing FeeStrategy interface; FeeCalculator uses polymorphism to apply different strategies without modification.
    3. Final Answer:

      Option A -> Option A
    4. Quick Check:

      New strategy class + polymorphism -> OCP compliance [check]
    Hint: Add new fee strategy class, no FeeCalculator changes [check]
    Common Mistakes:
    4. In the Tic-Tac-Toe game server, the makeMove() method is not synchronized. Which exact sequence of events between Thread 1 and Thread 2 can cause two players to place their marks on the same cell (double-booking)?
    medium
    A. Thread 1 and Thread 2 both call makeMove() but on different board instances.
    B. Thread 1 reads cell as empty, Thread 2 reads cell as occupied, both proceed to write.
    C. Thread 1 locks the board, Thread 2 waits, then both mark different cells simultaneously.
    D. Thread 1 checks cell is empty -> true, context switch before marking; Thread 2 checks cell is empty -> true, both mark cell concurrently.

    Solution

    1. Step 1: Identify the race condition in makeMove()

      Without synchronization, the check-then-act sequence is vulnerable: Thread 1 checks if cell is empty and is preempted before marking.
    2. Step 2: Trace Thread 2's actions

      Thread 2 also checks the same cell, sees it empty, and proceeds to mark it. Both threads mark the same cell, causing double-booking.
    3. Final Answer:

      Option D -> Option D
    4. Quick Check:

      Check-then-act gap without sync -> double-booking race [check]
    Hint: Check empty -> context switch -> both mark same cell [check]
    Common Mistakes:
    5. You need to add support for ElectricCar and ChargingSpot in the existing parking system using the command pattern. What is the minimum change to the current design to support this without modifying existing classes?
    hard
    A. Create a new ElectricCarCommand class that extends existing commands and override methods to handle charging spots
    B. Modify Vehicle class to add isElectric flag and add logic in existing commands to handle charging spots
    C. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar extends Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly
    D. Add charging logic inside existing ParkingLot class and modify commands to check for electric cars

    Solution

    1. Step 1: Identify extensibility requirements

      Adding new vehicle and spot types without modifying existing classes enforces OCP and avoids class explosion.
    2. Step 2: Evaluate options for minimal invasive change

      Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar extends Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly adds new enum values and new class, updating compatibility map without changing existing classes. Options B, C, D modify existing classes or add complex logic violating OCP.
    3. Final Answer:

      Option C -> Option C
    4. Quick Check:

      New enums and class added, existing classes unchanged [check]
    Hint: Add enums and classes, avoid modifying existing code [check]
    Common Mistakes:
    Recommended

    Ready to prove it?

    Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

    10 questions~5 mineasy hard