DEV Community

Cover image for Parking Lot System Design (LLD in Action) - Part-1
AnkitDevCode
AnkitDevCode

Posted on

Parking Lot System Design (LLD in Action) - Part-1

What is Low-Level Design (LLD)?

Low-Level Design (LLD) is the process of translating High-Level Design (HLD) into concrete implementation (like class diagrams, interfaces, object relationships, and design patterns) that can be directly implemented in code.

Core Components of LLD

You can find a more in-depth information of this concept in my earlier post Object-oriented programming System(OOPs)

  • Classes and Objects
  • Interfaces and Abstractions
  • Relationships Between Classes

Key Considerations for LLD

  • Scope & Requirements
  • Clear Data Models
  • Core Design Principles (SOLID & Beyond)
  • System Robustness & Scalability
  • Design Patterns & Reusability

Common Pitfalls to Avoid

  • God classes that handle too many responsibilities.
  • Inconsistent Data Models
  • Overuse of inheritance, leading to fragile hierarchies.
  • Ignoring non-functional requirements until it’s too late.
  • Overengineering: Don’t use complex patterns unless justified—keep it lean.

Parking Lot System

Problem Statement

Design a parking lot management system for a multi-story parking garage that can handle different types of vehicles, dynamic pricing, real-time availability tracking.

Focus: Low-Level Design (LLD), Object-Oriented Programming, System Architecture

Essential Questions to Ask:

  • What types of vehicles should the system support?
  • How many floors will the parking lot have?
  • What are the different parking spot sizes?
  • How should pricing work - hourly, flat rate, or both?
  • Do we need real-time availability tracking?
  • Should the system handle reservations?
  • What payment methods are supported?
  • Do we need administrative features?

❌ Red Flags - Poor Requirements Gathering

  • Jumping straight to code without understanding requirements
  • Making assumptions without asking questions
  • Not clarifying scope - building too much or too little
  • Ignoring edge cases early in the discussion

Good Approach - Identify Core Components

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   ParkingLot    │    │  ParkingFloor   │    │  ParkingSpot    │
│                 │────│                 │────│                 │
│ - Entry/Exit    │    │ - Spot Manager  │    │ - Vehicle       │
│ - Ticket Mgmt   │    │ - Availability  │    │ - Status        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │
         ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│     Vehicle     │    │     Payment     │    │  ParkingTicket  │
│                 │    │                 │    │                 │
│ - Type/Size     │    │ - Amount        │    │ - Entry/Exit    │
│ - License       │    │ - Method        │    │ - Spot Info     │
└─────────────────┘    └─────────────────┘    └─────────────────┘

┌─────────────────┐   
│ ParkingObserver │     
│                 │                     
│ - floorNumber   │    
│ - onSpotOccupied│    
└─────────────────┘   
Enter fullscreen mode Exit fullscreen mode

UML Diagram Analysis - Parking Lot System

The UML class diagram illustrates a comprehensive parking lot management system that demonstrates multiple design patterns and object-oriented principles. Let me break down each section:

Please find full diagram on kroki

Class Structure:

Vehicle (Abstract)
├── Motorcycle
├── Car  
├── Truck
└── ElectricCar
Enter fullscreen mode Exit fullscreen mode

UML Relationships Explained:

Inheritance (Generalization) - Solid Line with Empty Triangle:

Vehicle <|-- Motorcycle
Vehicle <|-- Car
Vehicle <|-- Truck
Vehicle <|-- ElectricCar
Enter fullscreen mode Exit fullscreen mode

Composition and Aggregation Relationships

Strong Composition (Filled Diamond):

ParkingLot "1" *-- "many" ParkingFloor
ParkingFloor "1" *-- "many" ParkingSpot
Enter fullscreen mode Exit fullscreen mode

Meaning:

  • Parking floors cannot exist without the parking lot
  • Parking spots cannot exist without their floor
  • Lifecycle dependency: Child objects destroyed when parent is destroyed

Weak Aggregation (Empty Diamond):

ParkingLot "1" o-- "many" ParkingObserver
Enter fullscreen mode Exit fullscreen mode

Meaning:

  • Observers can exist independently of the parking lot
  • Loose coupling: Observers can be shared across multiple parking lots

Simple Association (Solid Line):

ParkingSpot --> Vehicle : parkedVehicle
ParkingTicket --> ParkingSpot
ParkingTicket --> Payment
Enter fullscreen mode Exit fullscreen mode

Meaning:

  • Objects reference each other but are independent
  • Temporary relationships: Vehicle can move to different spots

Design Pattern Implementations

Strategy Pattern:

PricingStrategy (Interface)
├── HourlyPricingStrategy
└── FlatRatePricingStrategy

Enter fullscreen mode Exit fullscreen mode

UML Notation

PricingStrategy <|.. HourlyPricingStrategy
PricingStrategy <|.. FlatRatePricingStrategy
Enter fullscreen mode Exit fullscreen mode

  • Interface implementation relationship
  • Enables runtime strategy switching
  • Open/Closed Principle: Add new strategies without modifying existing code

Observer Pattern:

Relationship: ParkingLot "1" o-- "many" ParkingObserver
Enter fullscreen mode Exit fullscreen mode
  • Loose coupling: ParkingLot doesn't know concrete observer types
  • Event-driven: Automatic notifications on state changes

Factory Pattern:

  • Factory creates Vehicle instances but doesn't store references
  • Encapsulates creation logic: Hides vehicle instantiation complexity

Singleton Pattern:

  • Single instance guarantee: Only one parking lot can exist
  • Global access point: Available throughout the application

Builder Pattern:

Purpose: Constructs complex ParkingLot objects step by step

  • Fluent interface: Method chaining for easy configuration
  • Complex construction: Handles multi-floor setup with different spot types

Key Relationships Analysis

1. Vehicle ↔ ParkingSpot Interaction

  • Bidirectional relationship: Each knows about the other when parked
  • Validation logic: Vehicle determines if it can fit in spot

2. ParkingLot as Central Coordinator

  • Hub pattern: Central point for all parking operations
  • Dependency injection: Strategy and observers injected at runtime

Interface vs Abstract Class Decisions

Interfaces Used:

  • PricingStrategy: Behavior-only contract (no shared data)
  • ParkingObserver: Event handling contract (no shared implementation)

Abstract Classes Used:

  • Vehicle: Shared data (licensePlate, color) + abstract behavior

Decision Criteria:

Interface when: Pure behavior contract, no shared data
Abstract class when: Shared data + some abstract behaviors


Encapsulation and Access Modifiers

Field Visibility Patterns:

Private Fields (-):

  • All internal state in ParkingSpot, Payment, ParkingTicket
  • Information hiding: Implementation details not exposed

Protected Fields (#):

  • Vehicle class fields accessible to subclasses
  • Inheritance support: Subclasses can access parent data

Public Methods (+):

  • All service methods and getters
  • Clear API: Well-defined public interface

Thread Safety Considerations

ReentrantLock Usage:

  • ParkingSpot has individual locks for fine-grained control
  • ParkingFloor has floor-level locks for coordination
  • ParkingLot has system-wide locks for complex operations

Thread-Safe Collections:

  • Maps shown as ConcurrentHashMap implementations
  • Concurrent access: Multiple threads can safely access shared data

Summary: Good vs Bad Approaches

✅ What Makes This Solution Strong:

  • Clear Separation of Concerns: Each class has a single responsibility
  • Proper Abstraction: Abstract classes and interfaces used appropriately
  • Thread Safety: Comprehensive concurrency handling
  • Design Patterns: Multiple patterns used correctly (Strategy, Factory, Singleton, Observer)
  • Extensibility: Easy to add new features without breaking existing code
  • Error Handling: Graceful handling of edge cases
  • Type Safety: Enums prevent invalid states and types

🚩 Common Red Flags to Avoid:

  • God Class Anti-pattern: Single class doing everything
  • Primitive Obsession: Using strings/ints instead of proper types
  • No Thread Safety: Ignoring concurrent access issues
  • Tight Coupling: Classes knowing too much about each other
  • No Error Handling: Not handling edge cases
  • Hard-coded Values: No flexibility for configuration
  • Missing Abstractions: Not using inheritance where appropriate
  • Poor Naming: Unclear or misleading class/method names

What’s Next?

In this post, we walked through the low-level design of a Parking Lot System — identifying requirements, core entities, object relationships, and best practices for robust design.

In my next article, I’ll go a step further and design and code each component of the Parking Lot System in detail. We’ll translate the LLD into actual implementation, covering:

  • Class structures and method definitions
  • Applying design patterns where they fit
  • Handling edge cases and scalability concerns
  • Writing clean, maintainable code

References & Credits

AI tools were used to assist in research and writing but final content was reviewed and verified by the author.

Top comments (0)