My Solution for Design a Parking Lot

by zephyr_kaleidoscope326

Requirements


Functional Requirements

  • Assign the first fitting parking spot across floors when a vehicle arrives.
  • Generate a parking ticket containing vehicle details, assigned spot, and entry time.
  • Calculate parking fee on exit using PricingStrategy.
  • Handle the "Lot Full" scenario when no suitable spot exists.
  • Process parking payment using different payment methods.
  • Support adding and removing parking floors dynamically.

Non-Functional Requirements

  • System must be scalable to support multiple floors and many vehicles.
  • System must be extensible so new vehicle types, pricing strategies, or payment methods can be added easily.
  • The system must handle concurrency safely to prevent multiple vehicles from being assigned the same spot.
  • The system must maintain the correctness of the parking state and fee calculation.

Core Objects & Relationships

Based on the requirements and use cases, identify the main objects of the system and analyze how they interact and relate to each other...


Core Objects:

  • ParkingLot
  • ParkingFloor
  • ParkingSpot
  • PricingStrategy
  • Vehicle
  • EntryGate
  • ExitGage
  • Ticket
  • Payment


Relationships

ParkingLot

  • ParkingLot has many ParkingFloor (composition)
  • ParkingLot has one PricingStrategy
  • ParkingLot has many EntryGate
  • ParkingLot has many ExitGate


ParkingFloor

  • ParkingFloor has many ParkingSpot (composition)


ParkingSpot

  • ParkingSpot can be associated with at most one Vehicle at a time (0..1)


Ticket

  • Each Ticket is associated with exactly one Vehicle
  • Each Ticket is associated with exactly one ParkingSpot
  • Each Ticket may have zero or one Payment (0..1)


EntryGate

  • EntryGate creates/issues Ticket
  • EntryGate interacts with ParkingLot to allocate ParkingSpot
  • (dependency/behavioral interaction)


ExitGate

  • ExitGate uses PricingStrategy to calculate charges
  • ExitGate processes Payment
  • ExitGate closes Ticket


PricingStrategy

  • PricingStrategy defines the algorithm to calculate parking fees
  • Different implementations can exist (e.g., hourly, flat rate)



Relationship Summary by Type:

Composition:

ParkingLot -> ParkingFloor

ParkingFloor -> PrkingSpot


Association:

ParkingSpot -> Vehicle

Ticket -> Vehicle

Ticket -> ParkingSpot

Ticket -> payment


Dependency:

ExitGate -> PricingStrategy

ExitGate -> Payment

ExitGate -> Ticket


APIs & Class Members

For each class, define the attributes (data) it will hold and the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation. Write your code in the code editor below.


Vehicle

Attributes:

  • licensePlate : String
  • vehicleType : VehicleType

Methods:

  • getLicensePlate() : String
  • getVehicleType() : VehicleType


Car (implements Vehicle)

Attributes:

  • licensePlate : String

Methods:

  • getLicensePlate() : String
  • getVehicleType() : VehicleType


Truck (implements Vehicle)

Attributes:

  • licensePlate : String

Methods:

  • getLicensePlate() : String
  • getVehicleType() : VehicleType


ParkingSpot

Attributes:

  • id : String
  • spotType : SpotType
  • assignedVehicle : Vehicle
  • isAvailable : boolean

Methods:

  • canFit(Vehicle vehicle) : boolean
  • assignVehicle(Vehicle vehicle) : void
  • removeVehicle() : void
  • getId() : String
  • getSpotType() : SpotType
  • isAvailable() : boolean
  • getAssignedVehicle() : Vehicle


ParkingFloor

Attributes:

  • floorId : int
  • spots : List<ParkingSpot>

Methods:

  • findAvailableSpot(Vehicle vehicle) : Optional<ParkingSpot>
  • addSpot(ParkingSpot spot) : void
  • removeSpot(ParkingSpot spot) : void


ParkingLot

Attributes:

  • floors : List<ParkingFloor>
  • pricingStrategy : PricingStrategy

Methods:

  • findAvailableSpot(Vehicle vehicle) : Optional<ParkingSpot>
  • getPricingStrategy() : PricingStrategy


Ticket

Attributes:

  • ticketId : int
  • vehicle : Vehicle
  • spot : ParkingSpot
  • payment : Payment
  • entryTime : LocalDateTime
  • exitTime : LocalDateTime

Methods:

  • closeTicket() : void
  • attachPayment(Payment payment) : void
  • getSpot() : ParkingSpot
  • getEntryTime() : LocalDateTime
  • getExitTime() : LocalDateTime


EntryGate

Attributes:

  • ticketCounter : int

Methods:

  • issueTicket(Vehicle vehicle, ParkingLot parkingLot) : Ticket


ExitGate

Attributes:

  • paymentProcessor : PaymentProcessor

Methods:

  • processVehicleExit(Ticket ticket, ParkingLot parkingLot) : Payment


Payment

Attributes:

  • amount : double
  • status : PaymentStatus

Methods:

  • markSuccess() : void
  • getStatus() : PaymentStatus


PaymentProcessor

Methods:

  • processPayment(double amount) : Payment


CardPaymentProcessor (implements PaymentProcessor)

Methods:

  • processPayment(double amount) : Payment

UpiPaymentProcessor (implements PaymentProcessor)

Methods:

  • processPayment(double amount) : Payment


PricingStrategy

Methods:

  • calculateFee(Ticket ticket) : double


HourlyPricingStrategy (implements PricingStrategy)

Attributes:

  • hourlyRate : double

Methods:

  • calculateFee(Ticket ticket) : double



Deep Dive

Explain design tradeoffs you considered. Check and explain whether your design adheres to SOLID principles. Explain how your design can handle changes in scale and whether it would be easy to extend with new functionalities. Identify areas for future improvement...

Design Trade-off

The design prioritizes clarity and separation of responsibilities. The system is modeled using domain entities such as ParkingSpot, Payment, ParkingLot, PricingStrategy, etc. Each of these entities is designed to represent a specific responsibility within the parking system. This makes the system easier to understand and maintain, although it introduces more classes compared to a simpler procedural design.

The design also supports extensibility through interfaces such as PricingStrategy, which allows different pricing models to be implemented without modifying the existing system. This enables the system to support different pricing models such as hourly or flat pricing. The trade-off is that additional abstractions and classes are introduced, which increases complexity slightly but significantly improves extensibility.

Payment processing is handled through the PaymentProcessor interface. The ExitGate depends on this abstraction rather than a concrete payment implementation. This allows new payment methods to be added without modifying the ExitGate logic, which improves extensibility and reduces coupling between components.

Concurrency handling is implemented at the ParkingSpot level using a ReentrantLock to prevent multiple vehicles from being assigned to the same spot simultaneously. This improves the reliability of the system but introduces additional complexity due to synchronization management.


SOLID Compliance

SRP (Single Responsibility Principle)

The classes are designed to follow the Single Responsibility Principle. Each class is responsible for a specific part of the system.

Examples:

  • ParkingSpot manages the state of a specific parking spot.
  • Ticket represents a parking session for a vehicle.
  • ParkingFloor manages the collection of parking spots on a floor.
  • ExitGate handles the vehicle exit process.

This separation of responsibilities improves maintainability and readability.


OCP (Open–Closed Principle)

The system follows the Open–Closed Principle by using abstractions that allow behavior to be extended without modifying existing classes.

Examples include:

  • PricingStrategy allows new pricing models to be added.
  • PaymentProcessor allows new payment methods to be introduced.

This makes the system open for extension but closed for modification.


LSP (Liskov Substitution Principle)

The system follows the Liskov Substitution Principle through the use of the PricingStrategy interface. Different implementations such as HourlyPricingStrategy can substitute the base PricingStrategy type without affecting the correctness of the system.


ISP (Interface Segregation Principle)

The system uses small and focused interfaces such as PricingStrategy and PaymentProcessor. These interfaces define only the behavior required by implementing classes, ensuring that classes are not forced to implement methods that they do not need.

This keeps the design clean and avoids unnecessary dependencies between components.


DIP (Dependency Inversion Principle)

The design follows the Dependency Inversion Principle by ensuring that high-level modules depend on abstractions rather than concrete implementations.

For example, ExitGate depends on the PaymentProcessor interface instead of concrete payment classes. This reduces coupling and allows payment implementations to change without affecting higher-level components.


Scalability Consideration

The system is designed to scale by allowing additional parking floors and parking spots to be added without changing the core architecture.

Concurrency is handled at the ParkingSpot level using locks to ensure that multiple vehicles cannot occupy the same spot simultaneously. This helps maintain consistency in multi-threaded environments.

However, the current locking mechanism works only within a single application instance. If the system is deployed across multiple servers, this mechanism would not prevent race conditions across instances. In such cases, a distributed locking mechanism such as Redis-based locks or database row-level locking would be required.


Extensibility Consideration

The system is extensible in several areas:

  • New pricing models can be added by implementing the PricingStrategy interface.
  • New payment methods can be introduced by implementing the PaymentProcessor interface.
  • New vehicle types or parking spot types can be added with minimal changes to existing components.

This design allows the system to evolve as requirements change.


Future Improvements

Several improvements could further enhance the system:

  • Implement a distributed locking mechanism to support deployments across multiple servers.
  • Introduce a spot indexing structure such as Map<VehicleType, Queue<ParkingSpot>> to improve parking spot lookup performance.
  • Support EV charging spots as a new type of parking spot.
  • Introduce a reservation system that allows users to reserve parking spots in advance.
  • Implement dynamic pricing strategies that adjust parking rates based on occupancy or time of day.

Supports markdown