problemmediumooddesign-vehicle-parking-systemdesign vehicle parking systemdesignvehicleparkingsystem

Object-Oriented Design for a Parking Lot

MediumUpdated: Feb 14, 2023

Problem

Design an object-oriented multi-floor parking lot system that supports multiple entry/exit points, ticket issuance and payment, spot types (compact, large, handicapped, motorbike, electric), capacity tracking, per-hour pricing, and charging stations for electric vehicles. The system should allow admins and attendants to manage floors and spots; customers should be able to obtain tickets and pay via panels or attendants.

All existing diagrams and example code have been preserved and reorganized to the canonical OOD template.

Solution

1. Requirements Analysis

Functional Requirements:

  • Support multiple floors with multiple entry/exit panels.
  • Issue parking tickets at entrance panels and close them at exits.
  • Accept payments via exit panels, info portals, or attendants (cash/card).
  • Track different spot types (Handicapped, Compact, Large, Motorbike, Electric).
  • Support vehicle types and map vehicles to compatible spot types.
  • Display available spots per type on floor display boards.
  • Enforce capacity limits and refuse entry when full.
  • Support per-hour rate models and compute fees.

Non-Functional Requirements:

  • Reliability: ticketing and payment must be durable and consistent.
  • Scalability: handle many concurrent entries/exits and updates across floors.
  • Usability: clear displays for drivers and simple attendant portals.

Constraints & Assumptions:

  • Each physical copy (parking spot) is uniquely identifiable per floor.
  • Electric spots include charging/payment panels.

2. Use Case Diagram

Actors: Admin, Customer, ParkingAttendant, System

Use Cases: Add/Modify Floors & Spots, Issue Ticket, Scan/Pay Ticket, Update Rates, Show Availability

graph TD
    subgraph ParkingLot
        UC1(Add/Remove/Edit Floor)
        UC2(Add/Remove/Edit Spot)
        UC3(Take Ticket)
        UC4(Scan/Pay Ticket)
        UC5(Update Rates)
        UC6(Show Availability)
    end
    Admin --> UC1
    Admin --> UC2
    Customer --> UC3
    Customer --> UC4
    Attendant --> UC4
    System --> UC6

Parking Lot

3. Class Diagram

Core classes and responsibilities:

  • ParkingLot: singleton orchestrator for floors, panels, and active tickets.
  • ParkingFloor: contains spots, display board, and info portals.
  • ParkingSpot & subclasses: model spot types and occupancy.
  • ParkingTicket: issued at entry, closed at exit with payment details.
  • Account / Admin / ParkingAttendant: user roles and actions they may perform.
  • ParkingRate: defines per-hour pricing rules.
  • ParkingDisplayBoard: shows free spot numbers per type.
  • ElectricPanel: handles EV charging and payment.
classDiagram
    class ParkingLot { +String name +Address address }
    class ParkingFloor { +String name +List<ParkingSpot> spots }
    class ParkingSpot { +int number +ParkingSpotType type +is_free() }
    class ParkingTicket { +String ticketNumber +DateTime issuedAt +DateTime closedAt }
    class ParkingDisplayBoard { +show_empty_spot_number() }
    class ParkingRate { +get_rate_for_hours() }
    class Account { +String user_name +AccountStatus status }

    ParkingLot "1" -- "1..*" ParkingFloor : has
    ParkingFloor "1" -- "1..*" ParkingSpot : contains
    ParkingFloor "1" -- "1" ParkingDisplayBoard : shows

parking-class-diagram.png

4. Activity Diagram

Activity: Customer paying for a parking ticket

graph TD
    A[Customer arrives, takes ticket] --> B[Park vehicle]
    B --> C[On exit, scan ticket at exit panel]
    C --> D[Calculate fee based on ParkingRate]
    D --> E{Payment via card or cash?}
    E -- Card --> F[Process payment via Payment gateway]
    E -- Cash --> G[Attendant collects cash]
    F --> H[Mark ticket PAID and release exit]
    G --> H

parking-ticket.svg

5. High-Level Code Implementation

The original, detailed Python skeletons have been preserved (shortened only where appropriate to follow the skeleton guideline). Key enums, classes, and methods are below for quick reference.

from enum import Enum


class VehicleType(Enum):
    CAR = 1
    TRUCK = 2
    ELECTRIC = 3
    VAN = 4
    MOTORBIKE = 5


class ParkingSpotType(Enum):
    HANDICAPPED = 1
    COMPACT = 2
    LARGE = 3
    MOTORBIKE = 4
    ELECTRIC = 5


class AccountStatus(Enum):
    ACTIVE = 1
    BLOCKED = 2
    BANNED = 3


class ParkingTicketStatus(Enum):
    ACTIVE = 1
    PAID = 2
    LOST = 3


class Address:
    def __init__(self, street, city, state, zip_code, country):
        self.__street_address = street
        self.__city = city
        self.__state = state
        self.__zip_code = zip_code
        self.__country = country


class Person():
    def __init__(self, name, address, email, phone):
        self.__name = name
        self.__address = address
        self.__email = email
        self.__phone = phone


class Account:
    def __init__(self, user_name, password, person, status=AccountStatus.ACTIVE):
        self.__user_name = user_name
        self.__password = password
        self.__person = person
        self.__status = status

    def reset_password(self):
        pass


class ParkingSpot:
    def __init__(self, number, parking_spot_type):
        self.__number = number
        self.__free = True
        self.__vehicle = None
        self.__parking_spot_type = parking_spot_type

    def is_free(self):
        return self.__free

    def assign_vehicle(self, vehicle):
        self.__vehicle = vehicle
        self.__free = False

    def remove_vehicle(self):
        self.__vehicle = None
        self.__free = True


class ParkingFloor:
    def __init__(self, name):
        self.__name = name
        self.__handicapped_spots = {}
        self.__compact_spots = {}
        self.__large_spots = {}
        self.__motorbike_spots = {}
        self.__electric_spots = {}
        self.__info_portals = {}
        self.__display_board = ParkingDisplayBoard()

    def add_parking_spot(self, spot):
        # simplified: add spot to correct mapping
        pass


class ParkingDisplayBoard:
    def __init__(self, id=None):
        self.__id = id
        self.__handicapped_free_spot = None
        self.__compact_free_spot = None
        self.__large_free_spot = None
        self.__motorbike_free_spot = None
        self.__electric_free_spot = None

    def show_empty_spot_number(self):
        message = ""
        if self.__handicapped_free_spot and self.__handicapped_free_spot.is_free():
            message += "Free Handicapped: " + str(self.__handicapped_free_spot.get_number())
        else:
            message += "Handicapped is full"
        # ... other spot types
        print(message)


class ParkingLot:
    # singleton ParkingLot to ensure only one object in the system
    instance = None

    class __OnlyOne:
        def __init__(self, name, address):
            self.__name = name
            self.__address = address
            self.__parking_rate = None
            self.__entrance_panels = {}
            self.__exit_panels = {}
            self.__parking_floors = {}
            self.__active_tickets = {}

    def __init__(self, name, address):
        if not ParkingLot.instance:
            ParkingLot.instance = ParkingLot.__OnlyOne(name, address)
        else:
            ParkingLot.instance.__name = name
            ParkingLot.instance.__address = address

    def get_new_parking_ticket(self, vehicle):
        # synchronized access to issue a ticket
        ticket = ParkingTicket()
        # persist and update counts
        return ticket


class Transaction:
    def process_payment(self, amount: float, method: str) -> bool:
        return True

Parking UML

References

Comments