Bird
Raised Fist0

Restaurant Management System

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
🏗️
Restaurant Management System
Design a Restaurant Management System with Table, Menu, Order, Kitchen, Bill, and Staff management
mediumAdvanced LLD ChallengesFreq: medium
Prerequisites:OOP FundamentalsJava Concurrency BasicsDesign Patterns (Factory, Observer, Strategy)
⚙️
Functional Requirements
  • Assign customers to available tables
  • Place and update orders linked to tables
  • Track order status: Pending, Preparing, Ready, Served
  • Generate bills with itemized pricing and taxes
  • Support menu updates without downtime
  • Handle concurrent orders and billing safely
  • Allow staff login and role-based access
👤
Use Cases
  • Customer places an order at a table
  • Waiter assigns customers to tables
  • Chef views and updates order status in the kitchen
  • Cashier generates and processes bills
  • Manager updates menu items and prices
🧑‍💻
Actors
  • Customer
  • Waiter
  • Chef
  • Cashier
  • Manager
❓
Clarifying Questions to Ask
  • How many concurrent orders can the system handle? Are there multiple waiter threads?
  • Is pricing static or can it change dynamically during service hours?
  • How to handle partial order cancellations or modifications?
  • Are tables reusable immediately after bill payment or is there a cleaning delay?
  • Should the kitchen notify waiters asynchronously when orders are ready?
Out of Scope
✗ Online ordering and delivery
✗ Inventory management
✗ Customer loyalty programs
🔢
Enumerations
enum OrderStatus
PENDING | PREPARING | READY | SERVED | CANCELLED
Defines finite states of an order to prevent invalid transitions and enables exhaustive switch-case handling.
enum StaffRole
WAITER | CHEF | CASHIER | MANAGER
Encapsulates staff roles to enforce role-based access control and avoid string literal errors.
enum TableStatus
AVAILABLE | OCCUPIED | RESERVED | CLEANING
Tracks table lifecycle states to manage seating and cleaning workflows explicitly.
enum PaymentStatus
UNPAID | PAID | REFUNDED
Represents bill payment states to ensure correct billing lifecycle and concurrency safety.
📦
Table
3 fields
private final int tableIdprivate volatile TableStatus statusprivate int capacity
Manage table state and capacity, track occupancy and availability for seating customers.
public int getTableId()Returns the unique identifier of the table.
public TableStatus getStatus()Returns the current status of the table.
public synchronized void setStatus(TableStatus status)Atomically updates the table status to prevent race conditions.
public int getCapacity()Returns the seating capacity of the table.
📦
MenuItem
5 fields
private final int itemIdprivate String nameprivate double priceprivate String descriptionprivate volatile boolean available
Represent a menu item with pricing and availability status.
public int getItemId()Returns the unique identifier of the menu item.
public double getPrice()Returns the current price of the menu item.
public synchronized void setPrice(double price)Atomically updates the price to ensure visibility across threads.
public boolean isAvailable()Returns whether the menu item is currently available.
public synchronized void setAvailable(boolean available)Atomically updates availability to prevent inconsistent menu state.
📦
Order
5 fields
private final int orderIdprivate final int tableIdprivate final Map<MenuItem, Integer> itemsprivate volatile OrderStatus statusprivate final long timestamp
Track ordered items, their quantities, and order lifecycle status.
public synchronized void addItem(MenuItem item, int quantity)Atomically adds or updates item quantity in the order.
public synchronized void removeItem(MenuItem item)Atomically removes an item from the order.
public OrderStatus getStatus()Returns the current status of the order.
public synchronized void setStatus(OrderStatus status)Atomically updates the order status to prevent invalid concurrent updates.
public synchronized double getTotalPrice()Calculates total price based on items and their quantities.
📦
Bill
5 fields
private final int billIdprivate final int orderIdprivate volatile PaymentStatus paymentStatusprivate double totalAmountprivate double taxAmount
Generate and track payment status for orders, including tax calculations.
public synchronized void calculateTotal(double taxRate)Calculates total amount including tax atomically.
public PaymentStatus getPaymentStatus()Returns current payment status.
public synchronized void setPaymentStatus(PaymentStatus status)Atomically updates payment status to prevent double payments.
📦
Staff
4 fields
private final int staffIdprivate String nameprivate StaffRole roleprivate volatile boolean loggedIn
Represent staff members with role-based access and login state.
public synchronized boolean login()Atomically sets loggedIn to true if not already logged in.
public synchronized void logout()Atomically sets loggedIn to false.
public StaffRole getRole()Returns the role of the staff member.
📦
Kitchen
2 fields
private final Map<Integer, Order> activeOrdersprivate final Object lock
Manage active orders in the kitchen and notify staff on status changes.
public synchronized void addOrder(Order order)Atomically adds a new order to active orders.
public synchronized void updateOrderStatus(int orderId, OrderStatus status)Atomically updates order status and notifies observers.
public synchronized Order getOrder(int orderId)Returns the order by ID safely.
🔗
Relationships
Table◇──►Order[1..*]
aggregationOrder can exist independently of Table after creation
Order──►MenuItem[*..*]
associationMenuItem exists independently of Order
Order◆──►Bill[1..1]
compositionBill lifecycle bound to Order lifecycle
Staff──►Kitchen[1..1]
associationStaff and Kitchen exist independently
Kitchen◇──►Order[0..*]
aggregationOrders tracked by Kitchen but can exist independently
MenuItem──►MenuItem[1..1]
inheritanceSpecialized menu items can extend base MenuItem

Practice

(1/5)
1. In a vehicle rental system, should Vehicle be designed as an abstract class or an interface if it needs to hold common state like licensePlate and rentalStatus? Why?
easy
A. Abstract class, because it forces all subclasses to implement all methods explicitly.
B. Interface, because it allows multiple inheritance and enforces method signatures without state.
C. Interface, because Java interfaces can now have default methods and fields for state.
D. Abstract class, because it can hold shared state and provide default behavior for subclasses.

Solution

  1. Step 1: Analyze state requirements

    Vehicle needs to hold common mutable state like licensePlate and rentalStatus, which interfaces cannot hold as fields.
  2. Step 2: Choose correct OOP construct

    Abstract classes can have instance variables and default method implementations, making them suitable for shared state. Interfaces cannot hold instance state, only constants.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Shared mutable state -> abstract class, not interface [check]
Hint: Shared state needs abstract class, interfaces only define behavior [check]
Common Mistakes:
2. In the Car Rental System, the BookingManager class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here, and why is this the correct choice for managing bookings?
easy
A. Singleton pattern, to ensure only one BookingManager handles all bookings globally.
B. Prototype pattern, to clone BookingManager instances for concurrent booking handling.
C. Builder pattern, to construct complex BookingManager objects step-by-step.
D. Factory pattern, because it creates BookingManager instances on demand.

Solution

  1. Step 1: Identify the pattern from constructor and method

    A private constructor prevents external instantiation, and a static synchronized getInstance() method ensures a single shared instance, matching the Singleton pattern.
  2. Step 2: Reason why Singleton fits BookingManager

    BookingManager must coordinate all bookings centrally to avoid conflicts; multiple instances would cause inconsistent state, so Singleton ensures global coordination.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + static synchronized getInstance() -> Singleton [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
3. In the Online Blackjack game design, the Deck class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is this the correct choice?
easy
A. Singleton pattern to ensure only one Deck instance exists across the game
B. Prototype pattern to clone Deck instances for each player
C. Builder pattern to construct Deck with different card sets
D. Factory pattern to create multiple Deck instances safely

Solution

  1. Step 1: Identify the pattern from constructor and method

    A private constructor prevents external instantiation, and a static synchronized getInstance() ensures thread-safe single instance creation, matching Singleton pattern characteristics.
  2. Step 2: Why Singleton fits Deck

    Deck must be unique to maintain consistent card state and prevent duplication, so Singleton enforces a single shared deck.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + synchronized static method -> Singleton pattern [check]
Hint: Private constructor + static synchronized method -> Singleton [check]
Common Mistakes:
4. In a multi-threaded logging framework, the Appender class has a writeLog() method that first checks if the log file is open, then writes the log. Without synchronization on writeLog(), which exact thread interleaving causes lost log entries?
medium
A. Thread 1 writes log, Thread 2 waits for Thread 1 to finish, then writes.
B. Thread 1 checks file open -> true, context switch; Thread 2 checks file open -> true; both write simultaneously causing race.
C. Thread 1 closes file after writing; Thread 2 writes before file closes.
D. Thread 1 and Thread 2 both block waiting for file lock, causing deadlock.

Solution

  1. Step 1: Identify check-then-act race condition

    Without synchronization, Thread 1 checks file open and sees true, then context switches before writing. Thread 2 also checks and sees true, both proceed to write concurrently.
  2. Step 2: Why this causes lost logs

    Concurrent writes without synchronization cause race conditions, potentially overwriting or corrupting log entries.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap -> concurrent writes -> lost logs [check]
Hint: Check file open -> context switch -> both write -> race [check]
Common Mistakes:
5. To support ElectricCar needing ChargingSpot in the vending machine parking design, what is the minimum change that respects extensibility without modifying existing classes?
hard
A. Create a new ChargingSpot class extending Spot and modify ParkingLot to handle it specially.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
C. Modify existing Vehicle and Spot classes to add electric-specific fields and logic.
D. Add a boolean isElectric flag to Vehicle and Spot classes and add conditional logic everywhere.

Solution

  1. Step 1: Identify extensibility requirements

    Adding new vehicle and spot types without modifying existing classes preserves OCP and avoids class explosion.
  2. Step 2: Evaluate options for minimal invasive change

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility.COMPATIBILITY_MAP accordingly. adds new enum values and a subclass, updating compatibility map without changing existing classes. Others modify existing classes or add flags causing complexity.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New enums and subclass extend design without modifying existing classes [check]
Hint: Add enums + subclass + compatibility map, 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