Object-Oriented Parking Lot System Design: Core Architecture Analysis Based on Inheritance and Composition Patterns

Dec 01, 2025 · Programming · 9 views · 7.8

Keywords: Object-Oriented Design | Parking Lot System | Inheritance and Polymorphism

Abstract: This paper delves into the design and implementation of an object-oriented parking lot system, using an Amazon interview question as a starting point to systematically analyze the responsibility division and interaction logic of core classes such as ParkingLot, ParkingSpace, and Vehicle. It focuses on how inheritance mechanisms enable the classification management of different parking space types and how composition patterns build a parking lot status indication system. Through refactored code examples, the article details the implementation of key functions like vehicle parking/retrieval, space finding, and status updates, discussing the application value of design patterns in enhancing system scalability and maintainability.

In object-oriented programming, the design of a parking lot system is a classic interview problem that requires developers to abstract real-world entities into classes and define their interactions. Based on the requirements of an Amazon interview question, this paper designs an object-oriented parking lot system that manages three types of parking spaces (regular, handicapped, compact), displays full/empty status, and supports valet parking to find the nearest vacant space.

Core Class Design and Responsibility Division

The core classes of the system include ParkingLot, ParkingSpace, ParkingLotSign, and Parker (or Vehicle). ParkingLot, as the main entity of the parking lot, manages all parking spaces and maintains an array of vacant spaces sorted by distance from the entrance for quick lookup. ParkingSpace represents a single parking space with attributes like type and distance from the entrance, specialized through subclasses HandicappedParkingSpace, RegularParkingSpace, and CompactParkingSpace. ParkingLotSign is used to display the parking lot's status (e.g., full, empty, or normal) by calling methods like .Full(), .Empty(), or .Normal(). Parker represents a parker or vehicle, capable of performing park and unpark operations, with Valet as a subclass that can call ParkingLot.FindVacantSpaceNearestEntrance() to find the nearest vacant space.

Application of Inheritance and Polymorphism

Through inheritance mechanisms, different types of parking spaces and parkers can share base class attributes and methods while implementing specific behaviors. For example, HandicappedParkingSpace inherits from ParkingSpace and can add additional accessibility features; similarly, HandicappedParker and CompactParker as subclasses of Parker can override parking rules to accommodate special needs. This design enhances code reusability and extensibility, allowing easy addition of new parking space or parker types.

State Management and Interaction Flow

The status updates of the parking lot rely on collaboration among components. When Parker calls ParkingSpace.Take() or Vacate(), the parking space notifies ParkingLot of changes in occupancy. ParkingLot then checks the occupancy status and, if a change occurs (e.g., from not full to full), calls the corresponding method of ParkingLotSign to update the display. This event-driven design ensures state consistency and reduces coupling.

Code Implementation Example

The following is a simplified Java code example demonstrating the implementation of core classes. Note that the code is refactored based on an understanding of design concepts, not directly copied.

public class ParkingLot {
    private List<ParkingSpace> allSpaces;
    private List<ParkingSpace> vacantSpaces;
    private ParkingLotSign sign;

    public ParkingLot(List<ParkingSpace> spaces) {
        this.allSpaces = spaces;
        this.vacantSpaces = new ArrayList<>(spaces);
        this.sign = new ParkingLotSign();
        updateSign();
    }

    public ParkingSpace findNearestVacant(ParkingType type) {
        for (ParkingSpace space : vacantSpaces) {
            if (space.getType() == type) {
                return space;
            }
        }
        return null;
    }

    public void parkVehicle(Parker parker, ParkingType type) {
        ParkingSpace space = findNearestVacant(type);
        if (space != null) {
            space.take(parker);
            vacantSpaces.remove(space);
            updateSign();
        }
    }

    public void releaseVehicle(Parker parker) {
        for (ParkingSpace space : allSpaces) {
            if (space.isOccupiedBy(parker)) {
                space.vacate();
                vacantSpaces.add(space);
                updateSign();
                break;
            }
        }
    }

    private void updateSign() {
        if (vacantSpaces.isEmpty()) {
            sign.displayFull();
        } else if (vacantSpaces.size() == allSpaces.size()) {
            sign.displayEmpty();
        } else {
            sign.displayNormal();
        }
    }
}

public abstract class ParkingSpace {
    private ParkingType type;
    private int distanceFromEntrance;
    private Parker occupiedBy;

    public ParkingSpace(ParkingType type, int distance) {
        this.type = type;
        this.distanceFromEntrance = distance;
        this.occupiedBy = null;
    }

    public void take(Parker parker) {
        this.occupiedBy = parker;
    }

    public void vacate() {
        this.occupiedBy = null;
    }

    public boolean isOccupiedBy(Parker parker) {
        return this.occupiedBy != null && this.occupiedBy.equals(parker);
    }

    public ParkingType getType() { return type; }
}

public class HandicappedParkingSpace extends ParkingSpace {
    public HandicappedParkingSpace(int distance) {
        super(ParkingType.HANDICAPPED, distance);
    }
}

public enum ParkingType {
    REGULAR, HANDICAPPED, COMPACT
}

public class ParkingLotSign {
    public void displayFull() {
        System.out.println("Full");
    }

    public void displayEmpty() {
        System.out.println("Empty");
    }

    public void displayNormal() {
        System.out.println("Normal");
    }
}

public class Parker {
    private String id;

    public Parker(String id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Parker parker = (Parker) obj;
        return id.equals(parker.id);
    }
}

public class Valet extends Parker {
    public Valet(String id) {
        super(id);
    }

    public ParkingSpace findNearestSpace(ParkingLot lot, ParkingType type) {
        return lot.findNearestVacant(type);
    }
}

In this example, ParkingLot manages the list of spaces and status, ParkingSpace and its subclasses encapsulate space attributes, ParkingLotSign handles display logic, and Parker and Valet represent parkers. Through methods like findNearestVacant and updateSign, the system implements the required functionalities.

Design Considerations and Optimization Suggestions

In Answer 2, Vector and iterators are used to manage spaces, but in modern Java development, ArrayList and enhanced for-loops are recommended for better performance. Additionally, renaming Parker to Vehicle might align better with domain language, but clarity in class responsibilities should be ensured. To support concurrent access, synchronization mechanisms or thread-safe collections could be considered. Status updates could be further decoupled using the observer pattern, allowing ParkingLotSign to automatically respond to space changes.

Conclusion

The design of an object-oriented parking lot system demonstrates how to decompose complex requirements into manageable classes, utilizing inheritance, composition, and event-driven approaches to achieve modularity. Through the interaction of core classes, the system efficiently handles space allocation, status display, and special services like valet parking. In practical applications, developers should adjust the design based on specific scenarios, such as adding billing, reservation features, or integrating sensor data to build smarter parking solutions.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.