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

Hotel Management

Hard

Problem Summary

Design a Hotel Reservation and Management System managing multi-tier rooms (Standard, Deluxe, Suite), booking calendars, dynamic seasonal pricing, and housekeeping room turnover.

Functional Scope

  • Manage room categories: Standard, Deluxe, Suite, Presidential.
  • Date-range availability search preventing overlapping double-bookings.
  • Pluggable tariff pricing strategy (Weekday, Weekend, High-season, Corporate).
  • Check-in and keycard generation.
  • Observer pattern for housekeeping staff notification when guests checkout.

Entity-Relationship (ER) Schema

Hotel [1] --> [*] Room
Hotel [1] --> [1] BookingManager
Booking [1] --> [1] Room
Booking [1] --> [1] Guest
Hotel [1] --> [1] TariffStrategy

Design Approach

Apply the Strategy pattern for seasonal dynamic pricing and the Observer pattern to synchronize housekeeping workflows upon checkout.

Core Classes & Models

Hotel (Top-level hotel facade managing rooms and bookings)Room (RoomNo, RoomType: STANDARD, DELUXE, SUITE, Status: AVAILABLE, BOOKED, DIRTY)Booking (BookingId, room, guest, checkIn, checkOut, billAmount)TariffStrategy (WeekendSurgeTariff, HolidayTariff)HousekeepingObserver (Notifies cleaning staff on checkout)
Code Blueprint
89 lines
/**
 * Low-Level Design: Hotel Management System
 * Design Patterns Applied:
 *  - Factory Pattern: Room generation (Standard, Deluxe, Suite)
 *  - Observer Pattern: Housekeeping alerts and reservation notifications
 *  - Strategy Pattern: Seasonal dynamic room tariff pricing
 */

import java.util.*;

enum RoomType { STANDARD, DELUXE, SUITE }
enum RoomStatus { VACANT, OCCUPIED, CLEANING }

// --- [DESIGN PATTERN: Strategy] Dynamic room pricing strategy ---
interface TariffStrategy {
    double calculatePrice(RoomType type, boolean isHighSeason);
}

class SeasonalTariffStrategy implements TariffStrategy {
    @Override
    public double calculatePrice(RoomType type, boolean isHighSeason) {
        double base = switch (type) {
            case STANDARD -> 80.0;
            case DELUXE -> 150.0;
            case SUITE -> 300.0;
        };
        return isHighSeason ? base * 1.4 : base;
    }
}

// --- [DESIGN PATTERN: Observer] Housekeeping observer ---
interface HousekeepingObserver {
    void onCheckout(String roomNumber);
}

class HousekeepingService implements HousekeepingObserver {
    @Override
    public void onCheckout(String roomNumber) {
        System.out.println("🧹 [Housekeeping] Room " + roomNumber + " scheduled for sanitation.");
    }
}

class Room {
    private final String number;
    private final RoomType type;
    private RoomStatus status = RoomStatus.VACANT;

    public Room(String number, RoomType type) { this.number = number; this.type = type; }
    public String getNumber() { return number; }
    public RoomType getType() { return type; }
    public RoomStatus getStatus() { return status; }
    public void setStatus(RoomStatus status) { this.status = status; }
}

class Hotel {
    private final Map<String, Room> rooms = new HashMap<>();
    private final TariffStrategy tariffStrategy = new SeasonalTariffStrategy();
    private final List<HousekeepingObserver> observers = new ArrayList<>();

    public void addRoom(Room r) { rooms.put(r.getNumber(), r); }
    public void addObserver(HousekeepingObserver o) { observers.add(o); }

    public void checkIn(String roomNumber) {
        Room r = rooms.get(roomNumber);
        if (r != null && r.getStatus() == RoomStatus.VACANT) {
            r.setStatus(RoomStatus.OCCUPIED);
            System.out.println("🏨 Checked into Room " + roomNumber);
        }
    }

    public void checkOut(String roomNumber) {
        Room r = rooms.get(roomNumber);
        if (r != null) {
            r.setStatus(RoomStatus.CLEANING);
            for (HousekeepingObserver o : observers) o.onCheckout(roomNumber);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Hotel hotel = new Hotel();
        hotel.addObserver(new HousekeepingService());
        hotel.addRoom(new Room("101", RoomType.DELUXE));

        hotel.checkIn("101");
        hotel.checkOut("101");
    }
}