Parking Lot System
Problem Statement
Section titled “Problem Statement”Design a parking lot system that can manage multiple levels of parking, different vehicle types (motorcycle, car, truck), and handle parking/unparking operations. The system should efficiently allocate parking spots, calculate fees, and track parking availability.
Requirements
Section titled “Requirements”Functional Requirements
Section titled “Functional Requirements”- Support multiple vehicle types: Motorcycle, Car, Truck
- Handle multiple parking levels/floors
- Different spot sizes: Compact, Regular, Large
- Assign nearest available spot to vehicles
- Calculate parking fees based on duration
- Track spot availability in real-time
- Generate parking tickets with unique ID
- Support payment processing
- Handle entry and exit gates
Non-Functional Requirements
Section titled “Non-Functional Requirements”- Thread-safe for concurrent parking operations
- Fast spot lookup (O(1) or O(log n))
- Scalable to handle thousands of spots
- High availability
- Accurate fee calculation
Simplified Class Diagram
Section titled “Simplified Class Diagram”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
skinparam classBorderThickness 3skinparam ArrowThickness 1skinparam defaultFontSize 16skinparam classAttributeFontSize 18skinparam classFontSize 16
class ParkingLotService { + parkVehicle() + unparkVehicle() + getAvailableSpots()}
class ParkingFloor { + findAvailableSpot() + assignSpot() + releaseSpot()}
class ParkingSpot { + getSpotType() + isAvailable() + occupy() + vacate()}
class Vehicle { + getType() + getPlateNumber()}
class ParkingTicket { + getEntryTime() + getSpotNumber()}
class FeeCalculator { + calculateFee() + applyDiscounts()}
class PaymentProcessor { + processPayment()}
ParkingLotService *-- FeeCalculatorParkingLotService *-- PaymentProcessorParkingLotService o-- ParkingFloorParkingLotService ..> ParkingTicketParkingFloor o-- ParkingSpotParkingSpot --> VehicleParkingTicket --> Vehicle
@endumlSimplified Overview
Section titled “Simplified Overview”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam componentStyle rectangle
package "Core Service" { [ParkingLotService] as Service}
package "Parking Structure" { [ParkingFloor] as Floor [ParkingSpot] as Spot}
package "Vehicle & Ticket" { interface "IVehicle" as Vehicle [ParkingTicket] as Ticket}
package "Strategies" { interface "ISpotAssignmentStrategy" as SpotStrategy interface "IFeeCalculator" as FeeCalc interface "IPaymentProcessor" as Payment}
package "Gates" { [EntryGate] [ExitGate]}
[ParkingLotDriver] --> Service : usesService *-- Floor : composed ofService *-- SpotStrategy : composed ofService *-- FeeCalc : composed ofService *-- Payment : composed ofService o-- Ticket : managesFloor *-- Spot : containsSpot o-- Vehicle : parksEntryGate --> Service : usesExitGate --> Service : usesExitGate --> Payment : uses
@endumlDetailed Class Diagram
Section titled “Detailed Class Diagram”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
enum VehicleType { MOTORCYCLE CAR TRUCK + canFitIn(spotType: SpotType): boolean}
enum SpotType { COMPACT REGULAR LARGE + getSizeOrder(): int}
enum ParkingSpotStatus { AVAILABLE OCCUPIED RESERVED OUT_OF_SERVICE}
interface IVehicle { + getLicensePlate(): String + getType(): VehicleType}
class Vehicle { - licensePlate: String - type: VehicleType + Vehicle(licensePlate: String, type: VehicleType) + getLicensePlate(): String + getType(): VehicleType}
interface ISpotAssignmentStrategy { + findSpot(vehicle: IVehicle, floors: List<ParkingFloor>): ParkingSpot}
class NearestSpotStrategy { + findSpot(vehicle: IVehicle, floors: List<ParkingFloor>): ParkingSpot}
class RandomSpotStrategy { + findSpot(vehicle: IVehicle, floors: List<ParkingFloor>): ParkingSpot}
class ParkingSpot { - spotId: String - floor: int - type: SpotType - status: ParkingSpotStatus - currentVehicle: IVehicle + ParkingSpot(spotId: String, floor: int, type: SpotType) + isAvailable(): boolean + assign(vehicle: IVehicle): boolean + release(): IVehicle + canFitVehicle(vehicle: IVehicle): boolean + getStatus(): ParkingSpotStatus + setStatus(status: ParkingSpotStatus): void}
class ParkingFloor { - floorNumber: int - spots: Map<String, ParkingSpot> - availableSpotsByType: Map<SpotType, List<ParkingSpot>> + ParkingFloor(floorNumber: int) + addSpot(spot: ParkingSpot): void + findAvailableSpot(vehicle: IVehicle): ParkingSpot + getAvailableCount(type: SpotType): int + updateAvailability(spot: ParkingSpot): void}
interface IFeeCalculator { + calculateFee(ticket: ParkingTicket): double}
class HourlyFeeCalculator { - rateProvider: IRateProvider + HourlyFeeCalculator(provider: IRateProvider) + calculateFee(ticket: ParkingTicket): double}
class FlatFeeCalculator { - flatRate: double + calculateFee(ticket: ParkingTicket): double}
interface IRateProvider { + getRate(vehicleType: VehicleType): double + setRate(vehicleType: VehicleType, rate: double): void}
class ParkingRateProvider { - hourlyRates: Map<VehicleType, Double> + getRate(vehicleType: VehicleType): double + setRate(vehicleType: VehicleType, rate: double): void}
class ParkingTicket { - ticketId: String - vehicle: IVehicle - spot: ParkingSpot - entryTime: DateTime - exitTime: DateTime - fee: double + ParkingTicket(vehicle: IVehicle, spot: ParkingSpot) + setExitTime(time: DateTime): void + setFee(fee: double): void + getDuration(): long}
interface IPaymentProcessor { + processPayment(amount: double, method: String): boolean + refund(transactionId: String, amount: double): boolean}
class CashPaymentProcessor { + processPayment(amount: double, method: String): boolean + refund(transactionId: String, amount: double): boolean}
class CardPaymentProcessor { + processPayment(amount: double, method: String): boolean + refund(transactionId: String, amount: double): boolean}
interface IParkingService { + parkVehicle(vehicle: IVehicle): ParkingTicket + unparkVehicle(ticketId: String): double + getAvailableSpots(): int}
class ParkingLotService { - name: String - floors: List<ParkingFloor> - tickets: Map<String, ParkingTicket> - spotStrategy: ISpotAssignmentStrategy - feeCalculator: IFeeCalculator - paymentProcessor: IPaymentProcessor + ParkingLotService(name: String, strategy: ISpotAssignmentStrategy, calculator: IFeeCalculator, processor: IPaymentProcessor) + parkVehicle(vehicle: IVehicle): ParkingTicket + unparkVehicle(ticketId: String): double + addFloor(floor: ParkingFloor): void + getAvailableSpots(): int}
interface IGate { + getId(): String + isOperational(): boolean}
class EntryGate { - gateId: String - parkingService: IParkingService + EntryGate(gateId: String, service: IParkingService) + generateTicket(vehicle: IVehicle): ParkingTicket + getId(): String + isOperational(): boolean}
class ExitGate { - gateId: String - parkingService: IParkingService - paymentProcessor: IPaymentProcessor + ExitGate(gateId: String, service: IParkingService, processor: IPaymentProcessor) + processExit(ticket: ParkingTicket): double + getId(): String + isOperational(): boolean}
class ParkingLotDriver { + {static} main(args: String[]): void - setupParkingLot(): IParkingService - demonstrateParking(): void}
IVehicle <|.. VehicleVehicle *-- VehicleType
ParkingSpot *-- SpotTypeParkingSpot *-- ParkingSpotStatusParkingSpot o-- IVehicle : parks
ParkingFloor *-- ParkingSpot : contains
ISpotAssignmentStrategy <|.. NearestSpotStrategyISpotAssignmentStrategy <|.. RandomSpotStrategy
ParkingTicket o-- IVehicleParkingTicket o-- ParkingSpot
IFeeCalculator <|.. HourlyFeeCalculatorIFeeCalculator <|.. FlatFeeCalculatorHourlyFeeCalculator o-- IRateProviderIFeeCalculator ..> ParkingTicket : calculates
IRateProvider <|.. ParkingRateProvider
IPaymentProcessor <|.. CashPaymentProcessorIPaymentProcessor <|.. CardPaymentProcessor
IParkingService <|.. ParkingLotServiceParkingLotService *-- ParkingFloor : composed ofParkingLotService o-- ParkingTicket : managesParkingLotService *-- ISpotAssignmentStrategy : composed ofParkingLotService *-- IFeeCalculator : composed ofParkingLotService *-- IPaymentProcessor : composed of
IGate <|.. EntryGateIGate <|.. ExitGateEntryGate o-- IParkingService : usesExitGate o-- IParkingService : usesExitGate o-- IPaymentProcessor : uses
ParkingLotDriver ..> IParkingService : usesParkingLotDriver ..> IVehicle : createsParkingLotDriver ..> EntryGate : usesParkingLotDriver ..> ExitGate : uses
@endumlKey Design Patterns
Section titled “Key Design Patterns”- Singleton Pattern: ParkingLot ensures single instance
- Factory Pattern: Create different vehicle types
- Strategy Pattern: Different payment methods
- State Pattern: Parking spot status management
Design Pattern Diagrams
Section titled “Design Pattern Diagrams”1. Strategy Pattern - Fee Calculation & Spot Assignment
Section titled “1. Strategy Pattern - Fee Calculation & Spot Assignment”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
title Strategy Pattern - Flexible Pricing & Assignment
interface IFeeCalculator { + calculateFee(Ticket): double}
class HourlyFeeCalculator { - ratePerHour: double + calculateFee(Ticket): double}
class DailyFeeCalculator { - dailyRate: double + calculateFee(Ticket): double}
class WeekendFeeCalculator { - weekendMultiplier: double + calculateFee(Ticket): double}
interface ISpotAssignmentStrategy { + findSpot(VehicleType, List<ParkingSpot>): ParkingSpot}
class NearestSpotStrategy { + findSpot(VehicleType, List<ParkingSpot>): ParkingSpot}
class CheapestSpotStrategy { + findSpot(VehicleType, List<ParkingSpot>): ParkingSpot}
class ParkingLotService { - feeCalculator: IFeeCalculator - assignmentStrategy: ISpotAssignmentStrategy + setFeeCalculator(IFeeCalculator): void + setAssignmentStrategy(ISpotAssignmentStrategy): void}
IFeeCalculator <|.. HourlyFeeCalculatorIFeeCalculator <|.. DailyFeeCalculatorIFeeCalculator <|.. WeekendFeeCalculator
ISpotAssignmentStrategy <|.. NearestSpotStrategyISpotAssignmentStrategy <|.. CheapestSpotStrategy
ParkingLotService *-- IFeeCalculatorParkingLotService *-- ISpotAssignmentStrategy
note bottom of ParkingLotService **Code Example:**
// Weekday configuration service.setFeeCalculator(new HourlyFeeCalculator(5.0)); service.setAssignmentStrategy(new NearestSpotStrategy());
// Weekend configuration service.setFeeCalculator(new WeekendFeeCalculator(1.5));
// Airport parking (daily rate) service.setFeeCalculator(new DailyFeeCalculator(25.0)); service.setAssignmentStrategy(new CheapestSpotStrategy());end note
@enduml2. Factory Pattern - Vehicle Creation
Section titled “2. Factory Pattern - Vehicle Creation”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
title Factory Pattern - Vehicle Factory
class VehicleFactory { + {static} createVehicle(VehicleType, String): IVehicle + {static} createCar(String): Car + {static} createMotorcycle(String): Motorcycle + {static} createTruck(String): Truck}
interface IVehicle { + getType(): VehicleType + getLicensePlate(): String}
class Car { - licensePlate: String - type: VehicleType = CAR + getType(): VehicleType}
class Motorcycle { - licensePlate: String - type: VehicleType = MOTORCYCLE + getType(): VehicleType}
class Truck { - licensePlate: String - type: VehicleType = TRUCK + getType(): VehicleType}
VehicleFactory ..> IVehicle : createsIVehicle <|.. CarIVehicle <|.. MotorcycleIVehicle <|.. Truck
note left of VehicleFactory **Code Example:**
// Create vehicles without knowing concrete class IVehicle car = VehicleFactory.createVehicle( VehicleType.CAR, "ABC-123" );
IVehicle bike = VehicleFactory.createVehicle( VehicleType.MOTORCYCLE, "XYZ-789" );
// Factory handles instantiation logic IVehicle vehicle = VehicleFactory.createVehicle( userInputType, plateNumber );end note
@enduml3. State Pattern - Parking Spot Status
Section titled “3. State Pattern - Parking Spot Status”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startuml
title State Pattern - Parking Spot States
enum SpotStatus { AVAILABLE OCCUPIED RESERVED OUT_OF_SERVICE}
class ParkingSpot { - spotId: String - status: SpotStatus + markAvailable(): void + markOccupied(): void + markReserved(): void + markOutOfService(): void + isAvailable(): boolean}
note top of SpotStatus State transitions: AVAILABLE -> RESERVED -> OCCUPIED -> AVAILABLE Any state -> OUT_OF_SERVICE -> AVAILABLEend note
ParkingSpot *-- SpotStatus
note bottom of ParkingSpot **Code Example:**
ParkingSpot spot = new ParkingSpot("A-101", VehicleType.CAR);
// Initial state: AVAILABLE if (spot.isAvailable()) { spot.markReserved(); // Reserve during payment }
// After payment confirmed spot.markOccupied();
// Vehicle exits spot.markAvailable();
// Maintenance needed spot.markOutOfService();
// State transitions are managed internally // Invalid transitions can throw exceptionsend note
@endumlCode Snippets
Section titled “Code Snippets”Parking a Vehicle
Section titled “Parking a Vehicle”public class ParkingLot { public ParkingTicket parkVehicle(Vehicle vehicle) { synchronized(this) { ParkingSpot spot = findAvailableSpot(vehicle); if (spot == null) { throw new NoAvailableSpotException("No available spot for " + vehicle.getType()); }
spot.assignVehicle(vehicle); ParkingTicket ticket = new ParkingTicket(vehicle, spot); activeTickets.put(ticket.getTicketId(), ticket);
return ticket; } }
private ParkingSpot findAvailableSpot(Vehicle vehicle) { for (ParkingFloor floor : floors) { ParkingSpot spot = floor.findAvailableSpot(vehicle); if (spot != null) { return spot; } } return null; }}Spot Availability Check
Section titled “Spot Availability Check”public class ParkingSpot { public boolean canFitVehicle(Vehicle vehicle) { if (status != ParkingSpotStatus.AVAILABLE) { return false; }
switch(vehicle.getType()) { case MOTORCYCLE: return true; // Can fit in any spot case CAR: return type != SpotType.COMPACT; case TRUCK: return type == SpotType.LARGE; default: return false; } }}Fee Calculation
Section titled “Fee Calculation”public class ParkingTicket { public double calculateFee(ParkingRate rate) { if (exitTime == null) { exitTime = DateTime.now(); }
long durationMillis = exitTime.getMillis() - entryTime.getMillis(); double hours = Math.ceil(durationMillis / (1000.0 * 60 * 60));
this.fee = rate.calculateFee(vehicle, hours); return this.fee; }}Extension Points
Section titled “Extension Points”- Add reservation system for spots
- Implement dynamic pricing based on demand
- Add electric vehicle charging spots
- Implement valet parking service
- Add mobile app integration with QR code scanning
- Support monthly/annual parking passes
- Add parking spot navigation system