Designing a parking garage
A classic object-oriented design warm-up — model the entities, relationships, and rules of a multi-level parking lot before writing a line of code.
Why start here
Parking garage (and vending machine, next) are object-oriented design problems, not distributed-systems problems. They test whether you can take messy real-world rules and turn them into clean classes, relationships, and behaviors — the foundation under every larger system. No QPS math here; the skill is modeling.
Step 1 — Requirements
Functional:
- A garage has multiple levels, each with many spots.
- Spots come in types (motorcycle, compact, large/handicapped) and a vehicle fits certain types.
- A vehicle enters, is assigned a spot, gets a ticket; on exit it pays based on duration.
- Track availability (which spots are free) and show a full/space display.
Non-functional: correct spot assignment, support concurrent entries/exits (thread-safe), and be extensible — new vehicle types, new pricing, new spot types shouldn’t require rewrites.
Out of scope (state it): reservations, payments integration internals, multi-garage. Keep it one garage.
Step 2 — Identify the entities (the nouns)
Pull the core objects straight from the requirements:
- ParkingLot — the top-level system (often a singleton); holds levels.
- Level (ParkingFloor) — holds spots; tracks free spots per type.
- ParkingSpot — a single space, has a type and an occupied flag.
- Vehicle (abstract) → Motorcycle, Car, Truck/Bus — knows which spot types it can use.
- Ticket — issued on entry; records the spot, vehicle, and entry time.
- EntrancePanel / ExitPanel — issue tickets and process payment.
- ParkingRate / PricingStrategy — computes the fee from duration.
Step 3 — Relationships and the class sketch
ParkingLot 1──* Level 1──* ParkingSpot
Vehicle ──assigned──▶ ParkingSpot (via Ticket)
ExitPanel ──uses──▶ PricingStrategy ──reads──▶ Ticket
Use enums for fixed sets — VehicleType, SpotType, PaymentStatus — rather
than strings, so the compiler enforces validity.
Step 4 — The behaviors (the verbs)
parkVehicle(vehicle)→ find a compatible free spot, occupy it, issue a ticket.unparkVehicle(ticket)→ free the spot, compute the fee, take payment.findSpot(vehicle)→ the allocation policy (nearest level? first-fit by type?).isFull()/ availability counts per type.
Step 5 — Design patterns worth naming
This is where you score OOD points. Match a pattern to a requirement:
- Strategy —
PricingStrategyandSpotAllocationStrategyas pluggable policies, so pricing/allocation rules change without touching the lot. (Directly serves the extensibility requirement.) - Factory — a
VehicleFactory/SpotFactoryto create the right subtype. - Singleton — one
ParkingLotinstance. - Observer — the availability display subscribes to spot occupied/freed events and updates live.
- State — a spot or ticket moving through states (free → occupied → paid).
The interview cue
Lead with the entities and their relationships, use enums for types, and call out Strategy for pricing/allocation as your extensibility story. Then say “let me implement the core classes and the allocation algorithm” — which is exactly the next lesson. Modeling cleanly and naming one or two patterns with the requirement they satisfy is the whole game in an OOD round.