Behavioral PatternsObserver PatternMedium⏱️ ~3 min

Observer Pattern: Parking Lot Application

Domain: Parking Lot Management System where multiple displays and billing systems need to stay updated when parking spot availability changes.
Parking Lot Observer Design
«interface»
ParkingLotObserver
+ onSpotOccupied(spot): void
+ onSpotFreed(spot): void
DisplayBoard
- availableCount
+ update()
BillingSystem
- activeTickets
+ startBilling()
Analytics
- occupancyData
+ recordEvent()
◇ observed by
ParkingLot
- observers: List<Observer>
- spots: List<ParkingSpot>
+ registerObserver(o): void
+ removeObserver(o): void
+ parkVehicle(v, s): void
+ removeVehicle(s): void
Implementation Details:

ParkingLot (ConcreteSubject): Maintains the list of parking spots and observers. When parkVehicle() or removeVehicle() is called, it updates the spot status and then calls notifyObservers() with the specific event type.

DisplayBoard (ConcreteObserver): Tracks available spots by vehicle type. When notified via onSpotOccupied(), it decrements the count for that vehicle type. When notified via onSpotFreed(), it increments the count and updates the physical display.

BillingSystem (ConcreteObserver): Starts a billing session when a spot is occupied. Creates a Ticket object with entry time and spot reference. When the spot is freed, it calculates the fee based on duration and generates an invoice.

Analytics (ConcreteObserver): Records occupancy events for reporting. Maintains time-series data for peak hour analysis, average stay duration, and revenue projections. This observer is read-only and does not affect parking operations.

Notification Flow:
parkingLot.parkVehicle(vehicle, spot)
spot.occupy(vehicle)
notifyObservers(SPOT_OCCUPIED, spot)
Each observer receives onSpotOccupied(spot) and updates accordingly
Interview Tip: Explain that observers can be added/removed at runtime without modifying ParkingLot code. For example, adding a new EmailNotification observer during system evolution requires no changes to existing classes, demonstrating the Open/Closed Principle.
Design Decisions:

First, using separate methods (onSpotOccupied, onSpotFreed) instead of generic update() makes the interface more explicit and type-safe. Observers know exactly what event occurred without querying subject state.

Second, passing the affected ParkingSpot as parameter (push model) avoids each observer needing to iterate through all spots to find what changed. This is more efficient for large parking lots.

Third, if an observer fails (exception in onSpotOccupied()), the notification should continue to other observers. The ParkingLot should catch exceptions and log them but not propagate, ensuring one faulty observer does not break the entire system.

💡 Key Takeaways
ParkingLot notifies observers when spots are occupied or freed
Multiple observers react to same event differently
DisplayBoard updates available count, BillingSystem starts ticket, Analytics records data
Push model passes affected spot to avoid unnecessary queries
Observers can be added/removed without modifying ParkingLot
📌 Examples
1DisplayBoard showing real-time availability
2BillingSystem calculating parking fees
3Analytics tracking occupancy patterns
← Back to Observer Pattern Overview
Observer Pattern: Parking Lot Application | Observer Pattern - System Overflow