Bird
Raised Fist0

Hotel Management System

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
Room abstract class

Room is an abstract class with volatile boolean isOccupied and synchronized methods to manage occupancy state.

🎯 Tests understanding that abstract class is used because Room holds shared mutable state (isOccupied) which interfaces cannot hold in Java, and volatile ensures visibility across threads.
public abstract class Room {
    private int roomNumber;
    private volatile boolean isOccupied;
    public synchronized boolean isAvailable() {
        return !isOccupied;
    }
    public synchronized void occupy() {
        isOccupied = true;
    }
    public synchronized void vacate() {
        isOccupied = false;
    }
}
Booking composition with Room

Booking class composes Room, owning its lifecycle for the booking duration, and manages booking confirmation and cancellation.

🎯 Tests knowledge of composition relationship where Booking lifecycle controls Room usage, enforcing Single Responsibility Principle by separating booking logic from Room state.
public class Booking {
    private int bookingId;
    private Room room;
    private String guestName;
    public boolean confirmBooking() {
        synchronized(room) {
            if (room.isAvailable()) {
                room.occupy();
                return true;
            }
            return false;
        }
    }
    public void cancelBooking() {
        synchronized(room) {
            room.vacate();
        }
    }
}
HousekeepingTask composition in Hotel

Hotel class composes HousekeepingTask objects, managing their lifecycle and concurrency with synchronized methods.

🎯 Tests understanding of composition lifecycle ownership by Hotel and synchronized methods to prevent concurrent modification of housekeeping tasks.
public class HousekeepingTask {
    private int taskId;
    private Room room;
    private String status;
    public void startTask() {
        status = "In Progress";
    }
    public void completeTask() {
        status = "Completed";
    }
}
Hotel Singleton with synchronized getInstance

Hotel is a singleton with volatile static instance and synchronized getInstance method to ensure thread-safe lazy initialization.

🎯 Tests knowledge of volatile keyword preventing instruction reordering and synchronized method ensuring only one instance is created, avoiding partially constructed object visibility.
public class Hotel {
    private volatile static Hotel instance;
    private List<Room> rooms;
    private List<HousekeepingTask> tasks;
    private Hotel() {
        rooms = new ArrayList<>();
        tasks = new ArrayList<>();
    }
    public static synchronized Hotel getInstance() {
        if (instance == null) {
            instance = new Hotel();
        }
        return instance;
    }
    public synchronized boolean bookRoom(int roomNumber) {
        // booking logic
        return true;
    }
    public synchronized void assignTask(int roomNumber) {
        // housekeeping task assignment
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       |   <<Abstract>> |
       |      Room      |
       +----------------+
       | -roomNumber:int|
       | -isOccupied:   |
       |   volatile bool|
       +----------------+
       | +public sync'd boolean isAvailable()|
       | +public sync'd void occupy()       |
       | +public sync'd void vacate()       |
       +----------------+
               │
               │
       +----------------+
       |    Booking     |
       +----------------+
       | -bookingId:int |
       | -room: Room    |
       | -guestName:String|
       +----------------+
       | +public boolean confirmBooking()  |
       | +public void cancelBooking()      |
       +----------------+
               │
               │
       composition
       │ lifecycle owned by Booking
       +----------------+
       | HousekeepingTask|
       +----------------+
       | -taskId:int    |
       | -room: Room    |
       | -status:String |
       +----------------+
       | +public void startTask()          |
       | +public void completeTask()       |
       +----------------+
               │
               │
       composition
       │ lifecycle owned by Hotel
       +----------------+
       |     Hotel      |
       +----------------+
       | -rooms: List<Room>                 |
       | -tasks: List<HousekeepingTask>    |
       | -instance: volatile static Hotel  |
       +----------------+
       | +public static sync'd Hotel getInstance()|
       | +public sync'd boolean bookRoom(int)     |
       | +public sync'd void assignTask(int)      |
       +----------------+

This class diagram illustrates key Java-specific design decisions in a Hotel Management System. Room is modeled as an abstract class because it holds mutable state (isOccupied) requiring volatile for visibility and synchronized methods for atomic state changes. Booking composes Room, owning its lifecycle during booking, enforcing Single Responsibility Principle by separating booking logic from Room state. HousekeepingTask is composed by Hotel, which manages its lifecycle and concurrency with synchronized methods to avoid race conditions. Hotel is implemented as a thread-safe singleton using a volatile static instance and synchronized getInstance method to prevent partially constructed instances from being visible to other threads. These decisions ensure thread safety, proper lifecycle management, and extensibility following SOLID principles.

Primary Focus

✓ Composition lifecycle + Abstract class state + Synchronized methods concurrency + Singleton pattern

Practice

(1/5)
1. A logging framework has a Logger class with a private constructor and a static synchronized getInstance() method returning the single instance. Which design pattern is applied here and why is it the correct choice?
easy
A. Factory pattern, because it controls object creation centrally.
B. Prototype pattern, to clone Logger instances efficiently.
C. Builder pattern, to construct Logger with complex configurations.
D. Singleton pattern, ensuring only one Logger instance exists globally.

Solution

  1. Step 1: Identify the pattern from private constructor and static getInstance()

    The private constructor prevents external instantiation, and the static synchronized getInstance() ensures a single shared instance, which matches the Singleton pattern.
  2. Step 2: Why Singleton is correct here

    Logging frameworks require a single global Logger instance to coordinate log output consistently. Factory, Builder, and Prototype patterns do not enforce single instance semantics.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Private constructor + static synchronized getInstance() -> Singleton [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
2. In designing the Track abstraction for the music library, should Track be an abstract class or an interface? Consider that each Track has state like duration and title, and behavior like play() and pause().
easy
A. Interface, because state can be stored externally and behavior implemented in separate classes.
B. Interface, because it allows multiple inheritance and all methods are abstract.
C. Abstract class, because it can hold shared state and provide default behavior implementations.
D. Abstract class, because it enforces immutability of Track objects.

Solution

  1. Step 1: Analyze state and behavior requirements

    Track has shared state (duration, title) and common behavior (play, pause) that can be implemented once.
  2. Step 2: Abstract class vs interface for state and behavior

    Abstract class can hold state fields and provide default method implementations, while interfaces cannot hold instance state.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    State + default behavior -> abstract class [check]
Hint: Stateful base class? Use abstract class, not interface [check]
Common Mistakes:
3. You want to add a WeekendFeeStrategy to a parking system using the Observer pattern. According to SOLID principles, what is the minimum change required to support this new pricing without modifying existing classes?
medium
A. Modify the existing FeeStrategy class to add weekend logic with an if-else block.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy and register it as an observer without changing existing code.
C. Add a boolean flag in the Subject to indicate weekend and notify observers to adjust fees accordingly.
D. Create a subclass of the existing FeeStrategy with weekend logic and replace all references.

Solution

  1. Step 1: Identify SOLID principle involved

    Open-Closed Principle (OCP) requires adding new behavior without modifying existing code.
  2. Step 2: Evaluate options

    Modify the existing FeeStrategy class to add weekend logic with an if-else block. modifies existing class, violating OCP; Create a new WeekendFeeStrategy class implementing FeeStrategy and register it as an observer without changing existing code. adds new class but registering as observer for fee strategy is not typical; Create a subclass of the existing FeeStrategy with weekend logic and replace all references. requires replacing references, increasing coupling.
  3. Step 3: Add a boolean flag in the Subject to indicate weekend and notify observers to adjust fees accordingly. adds a weekend flag in Subject and notifies observers to adjust fees, allowing extension without modifying existing classes.

  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Weekend flag in Subject triggers observers -> new behavior without modifying existing classes [check]
Hint: OCP: add weekend flag and notify observers, no class changes [check]
Common Mistakes:
4. You want to add a WeekendFeeStrategy to calculate parking fees on weekends without modifying existing classes. Which SOLID principle guides this design and what is the minimum change?
medium
A. Add WeekendFeeStrategy implementing FeeStrategy and inject it, preserving OCP and DIP
B. Create a new subclass WeekendParkingLot duplicating most logic, violating DRY
C. Add a boolean flag in Vehicle to indicate weekend parking, violating SRP
D. Modify ParkingLot to add weekend logic directly, violating OCP but simpler

Solution

  1. Step 1: Identify applicable SOLID principles

    Open/Closed Principle (OCP) requires extending behavior without modifying existing code; Dependency Inversion Principle (DIP) requires depending on abstractions like FeeStrategy.
  2. Step 2: Apply minimal change preserving OCP and DIP

    Implement WeekendFeeStrategy as a new class implementing FeeStrategy and inject it where needed, avoiding changes to existing classes.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class + injection -> OCP and DIP preserved [check]
Hint: New strategy class + inject -> OCP and DIP preserved [check]
Common Mistakes:
5. ElectricCar requires ChargingSpots in the parking lot system. What is the minimum change to support this without modifying existing classes?
hard
A. Add a boolean isElectric flag to Vehicle and Spot classes and handle compatibility internally.
B. Modify Vehicle and Spot classes to add electric-specific fields and logic directly.
C. Create a new ElectricParkingLot subclass handling electric vehicles and spots separately.
D. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    To comply with OCP and avoid class explosion, new types should be added via enums and new subclasses without changing existing code.
  2. Step 2: Explain why Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally. fits minimal change

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally. adds new enum values and creates a new ElectricCar subclass, updating compatibility externally, preserving existing classes unchanged. Options B, C, and D modify existing classes or create subclasses that duplicate logic, violating OCP or SRP.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    New enums + subclass + external compatibility update -> minimal change [check]
Hint: Add enums + subclass + external map update -> no existing class changes [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard