Back to LLD explorer
Transactional / Concurrency• Patterns: Factory, Observer, Strategy

Airline Reservation

Hard

Problem Summary

Design an Airline Reservation System managing flight instances, multi-cabin inventory tiers (Economy, Business, First), temporary seat holds, PNR booking generation, and gate update alerts.

Functional Scope

  • Search flights by origin, destination, and travel date with multi-leg segments.
  • Multi-tier cabin seat inventory with dynamic yield pricing buckets.
  • Temporary 15-minute inventory hold during passenger detail checkout.
  • PNR (Passenger Name Record) generation upon payment verification.
  • Observer pattern for flight schedule change and gate departure notifications.

Entity-Relationship (ER) Schema

Flight [1] --> [*] FlightInstance
FlightInstance [1] --> [*] Seat
Booking [1] --> [1] FlightInstance
Booking [1] --> [*] Passenger

Design Approach

Apply optimistic locking with version checks or pessimistic row-locking on seat records to prevent double-booking under concurrent reservations.

Core Classes & Models

FlightInstance (FlightNumber, departureDate, aircraftSeatMap)Seat (SeatNo, CabinClass: ECONOMY, BUSINESS, FIRST, Status: AVAILABLE, HELD, BOOKED)Booking (PNR, passengers, seats, totalFare, BookingStatus)YieldPricingStrategy (Calculates dynamic fare based on bucket capacity remaining)NotificationObserver (Dispatches flight updates to passengers)
Code Blueprint
65 lines
/**
 * Low-Level Design: Airline Flight Reservation System
 * Design Patterns Applied:
 *  - Factory Pattern: Flight and passenger ticket instantiation
 *  - Observer Pattern: Flight delay, gate change, and boarding broadcasts
 *  - Strategy Pattern: Dynamic flight fare and baggage fee calculation
 */

import java.util.*;

enum FlightStatus { SCHEDULED, BOARDING, DELAYED, DEPARTED }

// --- [DESIGN PATTERN: Strategy] Airline fare pricing ---
interface FareStrategy {
    double calculateFare(double basePrice, int daysUntilFlight, boolean isPeakHoliday);
}

class DynamicFareStrategy implements FareStrategy {
    @Override
    public double calculateFare(double basePrice, int daysUntilFlight, boolean isPeakHoliday) {
        double multiplier = (daysUntilFlight < 7) ? 1.5 : 1.0;
        if (isPeakHoliday) multiplier *= 1.3;
        return basePrice * multiplier;
    }
}

// --- [DESIGN PATTERN: Observer] Flight departure alert listener ---
interface FlightUpdateListener {
    void onFlightDelayed(String flightNumber, int delayMinutes, String newGate);
}

class PassengerNotificationService implements FlightUpdateListener {
    @Override
    public void onFlightDelayed(String flightNumber, int delayMinutes, String newGate) {
        System.out.printf("✈️ [Passenger SMS] Flight %s delayed by %d mins. Proceed to Gate %s.%n", 
                          flightNumber, delayMinutes, newGate);
    }
}

class Flight {
    private final String flightNumber;
    private FlightStatus status = FlightStatus.SCHEDULED;
    private final List<FlightUpdateListener> listeners = new ArrayList<>();

    public Flight(String flightNumber) { this.flightNumber = flightNumber; }
    public void addListener(FlightUpdateListener l) { listeners.add(l); }

    public void delayFlight(int minutes, String newGate) {
        this.status = FlightStatus.DELAYED;
        for (FlightUpdateListener l : listeners) l.onFlightDelayed(flightNumber, minutes, newGate);
    }
}

public class Main {
    public static void main(String[] args) {
        Flight flight = new Flight("AI-101");
        flight.addListener(new PassengerNotificationService());

        DynamicFareStrategy pricing = new DynamicFareStrategy();
        double fare = pricing.calculateFare(200.0, 3, true);
        System.out.printf("Dynamically Priced Ticket: $%.2f%n", fare);

        flight.delayFlight(45, "B12");
    }
}