Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsMachine Coding Exercises
✓ FreeAdvanced· 8 min read

Parking Lot — Implementation

Part 2: turning the class design into a working allocation strategy, a swappable fee strategy, and handling the concurrency question every interviewer eventually asks.

Published September 23, 2026


Parking Lot — Implementation

Building on Parking Lot — Requirements & Class Design, this part makes two specific pieces of behavior swappable and handles the concurrency question that naturally follows.

Spot allocation as a Strategy

Part 1's findAvailableSpot just took the first fit. A real system might want "nearest to the entrance" or "match vehicle size as tightly as possible" (don't waste a large spot on a motorcycle) — exactly the shape Strategy Pattern solves.

interface SpotAllocationStrategy {
    Optional<ParkingSpot> findSpot(List<ParkingSpot> spots, Vehicle vehicle);
}

class NearestAvailableStrategy implements SpotAllocationStrategy {
    public Optional<ParkingSpot> findSpot(List<ParkingSpot> spots, Vehicle vehicle) {
        return spots.stream().filter(s -> !s.isOccupied() && s.canFit(vehicle)).findFirst(); // spots pre-sorted by distance
    }
}

class BestFitStrategy implements SpotAllocationStrategy {
    public Optional<ParkingSpot> findSpot(List<ParkingSpot> spots, Vehicle vehicle) {
        return spots.stream()
            .filter(s -> !s.isOccupied() && s.canFit(vehicle))
            .min(Comparator.comparing(ParkingSpot::sizeRank)); // smallest spot that still fits — avoids wasting large spots
    }
}

ParkingLot now takes a SpotAllocationStrategy in its constructor instead of hard-coding "first fit" — the allocation policy is chosen once, at construction, and can be swapped without touching ParkingLot's own code at all, exactly matching the Strategy Pattern's core benefit.

Fee calculation as its own Strategy

interface FeeStrategy {
    double calculateFee(Ticket ticket, Instant exitTime);
}

class HourlyFeeStrategy implements FeeStrategy {
    private static final double RATE_PER_HOUR = 5.0;
    public double calculateFee(Ticket ticket, Instant exitTime) {
        long minutes = Duration.between(ticket.getEntryTime(), exitTime).toMinutes();
        return Math.ceil(minutes / 60.0) * RATE_PER_HOUR; // round up to the next full hour
    }
}

class FlatDailyRateStrategy implements FeeStrategy {
    public double calculateFee(Ticket ticket, Instant exitTime) {
        return 25.0; // flat rate regardless of duration, e.g. for an event lot
    }
}

Separating FeeStrategy from SpotAllocationStrategy (rather than one big "ParkingPolicy" class doing both) follows the Single Responsibility Principle directly — a change to pricing shouldn't risk touching allocation logic, and vice versa, and each can be tested and swapped completely independently.

Concurrency: two vehicles requesting the same spot simultaneously

The naive findSpot() + park() sequence from Part 1 has an obvious race: two threads could both see the same spot as available before either marks it occupied — the classic check-then-act race (see Concurrent Utilities & Coordination and HashMap Concurrency Variants for the same shape of bug elsewhere).

class ParkingSpot {
    private final ReentrantLock lock = new ReentrantLock(); // per-spot lock — fine-grained, not a lock on the whole lot
    private volatile boolean occupied = false;
    private Vehicle parkedVehicle;

    boolean tryPark(Vehicle vehicle) {
        lock.lock();
        try {
            if (occupied) return false; // lost the race — someone else got here first
            occupied = true;
            parkedVehicle = vehicle;
            return true;
        } finally {
            lock.unlock();
        }
    }
}

Where to put the lock matters: a single lock guarding the entire ParkingLot would be correct but serializes every parking attempt across the whole facility — a huge, unnecessary bottleneck for a large lot with hundreds of independent spots. Locking per spot (as above) means only two threads racing for the same specific spot ever contend at all; threads targeting different spots proceed fully in parallel. This is the same fine-grained-locking principle behind ConcurrentHashMap's per-bucket locking (see HashMap Concurrency Variants) — lock the smallest unit that actually needs protecting, not the whole structure.

The calling code now needs to handle a failed tryPark() by retrying against the next candidate spot, not just giving up — the allocation strategy's findSpot() returns a candidate, but tryPark() is the actual atomic claim, and losing that race means falling back to the next candidate in the list.

Follow-up questions this topic invites — and their answers

Q: Why volatile AND a lock on the same field — isn't that redundant? A: The lock protects the compound check-then-set operation (atomicity); volatile on occupied additionally guarantees that a thread reading the spot's status without acquiring the lock (e.g. for a dashboard showing live occupancy) still sees the latest value rather than a stale cached one — belt-and-suspenders for two different guarantees, not true redundancy.

Q: Could you avoid locking entirely using CAS instead? A: Yes — an AtomicBoolean occupied with compareAndSet(false, true) achieves the same atomic claim without an explicit lock, and for a simple boolean flip like this, CAS is arguably a cleaner fit than a full ReentrantLock (see Visibility & Memory Model's coverage of CAS-based atomic classes).

Q: How would FeeStrategy and SpotAllocationStrategy be chosen at runtime — hard-coded, or configurable? A: A Factory (see Factory & Abstract Factory) is the natural fit — a ParkingLotFactory could construct a ParkingLot with different strategy combinations for different facility types (an airport lot with BestFitStrategy + HourlyFeeStrategy, an event lot with NearestAvailableStrategy + FlatDailyRateStrategy), keeping that combinatorial choice in one place.

Previous

Parking Lot — Requirements & Class Design

Next

Elevator System — Requirements & Class Design

AI Tutor

Lesson: Parking Lot — Implementation

Quick actions

AI responses can be inaccurate. Verify critical information.