Design a Hotel Booking System
OOP design for a hotel booking system covering room inventory, reservation management, date-range conflict detection, pricing strategies, and cancellation policies.
The Problem
Your company operates a hotel chain with 12 properties across the country. The current reservation system is a spreadsheet shared between front desk staff. Double bookings happen weekly because two agents can sell the same room for overlapping dates without any conflict detection. Last month a guest arrived for their anniversary suite to find it already occupied.
Hotel booking is fundamentally a date-range conflict problem. Unlike point-in-time availability (parking lot, vending machine), you need to check whether a requested date range overlaps with any existing reservation. The interviewer wants to see clean entity separation, a robust availability algorithm, pluggable pricing strategies, and a well-defined reservation lifecycle.
Design the core classes for a hotel booking system that handles room inventory management, date-range availability checking, reservation creation with conflict prevention, dynamic pricing, and cancellation with refund policies.
Requirements
Clarifying Questions
Before jumping into class design, ask questions to turn the vague prompt into a concrete specification. Cover four areas: core actions, error handling, boundaries, and future extensions.
You: "What room types does the hotel support? Are they fixed categories or configurable?"
Interviewer: "Fixed categories for now: single, double, deluxe, and suite. Each has a base price per night."
Four room types as an enum. That keeps things simple but extensible.
You: "Can a single reservation cover multiple rooms, or is it one room per booking?"
Interviewer: "One room per reservation. If a guest wants two rooms, that is two separate reservations."
Good. One-to-one between reservation and room simplifies the model significantly. No need for a "reservation group" concept.
You: "How does pricing work? Is it a flat rate per night, or does it vary by season or demand?"
Interviewer: "The system should support multiple pricing strategies: standard flat rate, seasonal pricing, and weekend surcharges. The hotel manager can configure which strategy applies."
Multiple pricing strategies with runtime selection. That is a clear Strategy pattern signal.
You: "What happens when two agents try to book the same room for overlapping dates simultaneously?"
Interviewer: "Only one should succeed. The system must prevent double bookings even under concurrent requests."
Concurrency control on availability checking. You will need synchronized access or optimistic locking.
You: "What cancellation policies should the system support?"
Interviewer: "Free cancellation up to 24 hours before check-in, partial refund between 24 and 6 hours, and no refund after that. But the policy should be configurable per room type."
Another Strategy pattern candidate for cancellation policies.
You: "Should the system send notifications when a booking is confirmed or cancelled?"
Interviewer: "Yes, email and SMS notifications on booking confirmation, cancellation, and check-in reminders."
Multiple notification channels triggered by booking events. That is an Observer pattern signal.
You: "Is payment processing in scope?"
Interviewer: "Model it as an interface. The booking service calls it, but you do not design the payment gateway internals."
You: "Should we handle check-in and check-out operations, or just the reservation itself?"
Interviewer: "Include them. A reservation moves through states: pending, confirmed, checked-in, checked-out, or cancelled."
That confirms the reservation has a state machine lifecycle.
Perfect. You have clarified scope and ruled out unnecessary complexity.
Final Requirements
Functional Requirements:
- The system manages rooms across multiple types (single, double, deluxe, suite) with per-type base pricing
- Guests can search for available rooms by date range and room type
- The system creates reservations with date-range conflict detection (no double bookings)
- Pricing is calculated per reservation using configurable strategies (standard, seasonal, weekend)
- Cancellations follow configurable refund policies based on time until check-in
- Reservations transition through a defined lifecycle: PENDING, CONFIRMED, CHECKED_IN, CHECKED_OUT, CANCELLED
Non-Functional Requirements:
- Concurrent booking attempts for the same room and dates must be handled safely (only one succeeds)
- Adding a new pricing strategy or cancellation policy requires a new class, not changes to existing code
- Booking events trigger notifications through multiple channels (email, SMS)
Out of Scope:
- Payment gateway internals (use an interface)
- Multi-hotel chain management (single hotel for now)
- UI rendering
- Persistence / database layer
- Guest authentication
- Room service or amenity management
Example Inputs and Outputs
Scenario 1: Successful booking
- Input: Guest searches for a deluxe room, Jan 15-18 (3 nights). Two deluxe rooms exist. Room D1 has a reservation Jan 10-16 (overlaps). Room D2 is free.
- Expected: System returns Room D2 as available. Guest books D2. Reservation is created with status CONFIRMED. Price calculated at 3 x $200/night = $600 (standard pricing). Email and SMS confirmations sent.
- Why: Validates date-range overlap detection and the notification flow.
Scenario 2: Double booking prevention
- Input: Two agents simultaneously attempt to book Room S1 for Jan 20-22.
- Expected: First request succeeds with CONFIRMED status. Second request fails with "Room unavailable for selected dates." No partial state left behind.
- Why: Validates concurrent conflict detection.
Scenario 3: Cancellation with partial refund
- Input: Guest cancels a confirmed reservation 12 hours before check-in. Policy allows 50% refund between 6-24 hours.
- Expected: Reservation status changes to CANCELLED. Refund of 50% is issued. Room becomes available for the cancelled dates. Cancellation notification sent.
- Why: Validates the cancellation policy strategy and state transition.
Try It Yourself
Try it yourself
Before reading the solution, spend 15-20 minutes sketching your own class diagram. Focus on the date-range overlap algorithm and how you would prevent two reservations from claiming the same room for overlapping dates. Compare your approach with the walkthrough below.
Step 1: Identify Core Entities
Start by asking: what are the main "things" in this problem? Look at the nouns in your requirements. You have rooms, guests, reservations, room types, pricing, cancellation policies, and notifications. Each maps to a class or enum with a single, clear job.
A common mistake is putting everything into a single Hotel god class that manages rooms, handles bookings, calculates prices, and sends emails. Good design means each class has one responsibility.
| Entity | Responsibility | Key attributes |
|---|---|---|
| Room | Represents a physical room with its type and capacity | roomNumber, type, basePrice, capacity |
| RoomType | Enum of room categories with associated base pricing | SINGLE, DOUBLE, DELUXE, SUITE |
| Guest | Holds guest contact information for notifications | name, email, phone |
| Reservation | Tracks a booking's dates, room, guest, price, and lifecycle state | checkIn, checkOut, room, guest, status, totalPrice |
| ReservationStatus | Enum for the reservation state machine | PENDING, CONFIRMED, CHECKED_IN, CHECKED_OUT, CANCELLED |
| PricingStrategy | Interface for calculating the price of a stay | calculatePrice(room, checkIn, checkOut) |
| CancellationPolicy | Interface for computing refund amounts | calculateRefund(reservation) |
| BookingService | Orchestrator: checks availability, creates reservations, prevents conflicts | rooms, reservations, pricingStrategy |
| NotificationService | Observer that reacts to booking events and dispatches alerts | observers list, notify() |
Notice that BookingService is the orchestrator while Room and Guest are data holders. PricingStrategy and CancellationPolicy are behavior interfaces. Separating pricing from the room means you can swap pricing algorithms without touching the room class.
Step 2: Define Relationships and Class Design
Class Diagram
Deriving State and Methods
Reservation
The reservation is the central entity. It tracks who booked which room, for what dates, at what price, and in what lifecycle state.
Deriving state from requirements:
| Requirement | What Reservation must track |
|---|---|
| "Guests search by date range" | Check-in and check-out dates |
| "Date-range conflict detection" | Dates must support overlap comparison |
| "Pricing calculated per reservation" | Total price for the stay |
| "Reservations transition through lifecycle" | Current status (enum) |
| "One room per reservation" | The booked room |
| "Cancellation notification sent" | The guest (for contact info) |
This gives us the core state: room, guest, checkIn, checkOut, totalPrice, status, and id.
Deriving methods from needs:
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with NotesFromSDE Premium.