Bird
Raised Fist0
LLDsystem_design~7 mins

Restaurant, Menu, Order classes in LLD - System Design Guide

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Problem Statement
When designing a restaurant ordering system, mixing responsibilities in a single class leads to code that is hard to maintain and extend. For example, if the Order class also manages menu items and restaurant details, changes in one area can break unrelated parts, causing bugs and slowing development.
Solution
Separate the system into distinct classes: Restaurant to hold restaurant details, Menu to manage available dishes, and Order to handle customer orders. Each class has a clear responsibility, making the code easier to understand, test, and modify independently.
Architecture
┌─────────────┐     ┌───────────┐     ┌───────────┐
│ Restaurant  │────▶│   Menu    │────▶│   Order   │
└─────────────┘     └───────────┘     └───────────┘

This diagram shows the flow where Restaurant contains or references Menu, and Menu is used by Order to create customer orders.

Trade-offs
✓ Pros
Clear separation of concerns improves maintainability and readability.
Easier to add new features like multiple menus or order types without affecting other parts.
Simplifies testing each class independently.
✗ Cons
More classes increase initial complexity for beginners.
Requires careful design to manage interactions between classes.
May introduce slight overhead in communication between classes.
Use when building any restaurant or food ordering system that needs to scale beyond simple scripts, especially if multiple menus or order types exist.
Avoid if the system is a very simple script with only one menu and no plans for extension, where added classes add unnecessary complexity.
Real World Examples
Uber Eats
Separates restaurant info, menu items, and customer orders to allow dynamic menu updates without affecting order processing.
DoorDash
Uses distinct classes to manage restaurant details, menus, and orders enabling flexible promotions and order tracking.
Grubhub
Maintains separate models for restaurants, menus, and orders to support multiple cuisines and complex order customizations.
Code Example
The before code mixes restaurant, menu, and order logic in one class, making it hard to maintain. The after code separates concerns: Restaurant holds a Menu, Menu manages items, and Order uses Menu to validate and place orders. This separation improves clarity and extensibility.
LLD
### Before (all responsibilities mixed in one class)
class RestaurantOrder:
    def __init__(self, name):
        self.name = name
        self.menu_items = {}
        self.orders = []

    def add_menu_item(self, item_name, price):
        self.menu_items[item_name] = price

    def place_order(self, item_name):
        if item_name in self.menu_items:
            self.orders.append(item_name)
        else:
            print("Item not on menu")


### After (separated classes)
class Restaurant:
    def __init__(self, name):
        self.name = name
        self.menu = Menu()

class Menu:
    def __init__(self):
        self.items = {}

    def add_item(self, item_name, price):
        self.items[item_name] = price

    def has_item(self, item_name):
        return item_name in self.items

class Order:
    def __init__(self, menu):
        self.menu = menu
        self.ordered_items = []

    def place_order(self, item_name):
        if self.menu.has_item(item_name):
            self.ordered_items.append(item_name)
        else:
            print("Item not on menu")
OutputSuccess
Alternatives
Monolithic Class
Combines restaurant, menu, and order logic into one class without separation.
Use when: Only for very simple, one-off scripts with no future extension planned.
Database-Driven Design
Focuses on database schema design first, then generates classes, rather than designing classes first.
Use when: When database design is the primary concern and object models follow from it.
Summary
Separating Restaurant, Menu, and Order into distinct classes prevents code entanglement and eases maintenance.
Each class has a clear responsibility, improving readability and enabling independent changes.
This design supports scalability for complex restaurant ordering systems with multiple menus and order types.

Practice

(1/5)
1. Which class should primarily hold the list of available food items and their prices in a restaurant system?
easy
A. Restaurant
B. Menu
C. Order
D. Customer

Solution

  1. Step 1: Understand the role of Menu class

    The Menu class is designed to store food items and their prices, acting as the restaurant's catalog.
  2. Step 2: Differentiate from other classes

    Order tracks customer requests, Restaurant manages overall operations, Customer represents the diner. Only Menu holds items and prices.
  3. Final Answer:

    Menu -> Option B
  4. Quick Check:

    Menu = items and prices [OK]
Hint: Menu holds items and prices, not orders or customers [OK]
Common Mistakes:
  • Confusing Order with Menu
  • Thinking Restaurant holds item prices
  • Assuming Customer stores menu data
2. Which of the following is the correct way to add a new item to the Menu class in a typical object-oriented design?
easy
A. menu.addItem('Pizza', 12.99)
B. Menu.add('Pizza', 12.99)
C. menu.insertItem('Pizza', 12.99)
D. addItem(menu, 'Pizza', 12.99)

Solution

  1. Step 1: Identify instance method usage

    Adding an item to a Menu instance uses the instance method, so calling menu.addItem(...) is correct.
  2. Step 2: Eliminate incorrect syntax

    Menu.add(...) suggests a static method which is unlikely; insertItem is not standard; addItem(menu, ...) is procedural, not OOP style.
  3. Final Answer:

    menu.addItem('Pizza', 12.99) -> Option A
  4. Quick Check:

    Instance method call = menu.addItem(...) [OK]
Hint: Use instance.method() to add items, not static or procedural calls [OK]
Common Mistakes:
  • Using static method call instead of instance method
  • Confusing method names
  • Calling functions outside class context
3. Given the following code snippet, what will be the total cost of the order?
menu = Menu()
menu.addItem('Burger', 5.0)
menu.addItem('Fries', 2.5)
order = Order(menu)
order.addItem('Burger', 2)
order.addItem('Fries', 3)
total = order.calculateTotal()
medium
A. 17.5
B. 15.0
C. 20.0
D. 12.5

Solution

  1. Step 1: Calculate cost for each item

    Burger price is 5.0, quantity 2 -> 5.0 * 2 = 10.0; Fries price is 2.5, quantity 3 -> 2.5 * 3 = 7.5.
  2. Step 2: Sum the costs

    Total cost = 10.0 + 7.5 = 17.5.
  3. Final Answer:

    17.5 -> Option A
  4. Quick Check:

    (5*2)+(2.5*3) = 17.5 [OK]
Hint: Multiply price by quantity, then add all items [OK]
Common Mistakes:
  • Adding quantities instead of multiplying by price
  • Forgetting to multiply price by quantity
  • Mixing up item prices
4. In a system where the Order class adds items without checking the Menu, what is the main issue that can occur?
medium
A. Order will reject all items by default
B. Menu prices will automatically update in Order
C. Order may include items not available in the Menu
D. Restaurant will close automatically

Solution

  1. Step 1: Understand the role of validation

    Order should verify items exist in Menu to avoid invalid orders.
  2. Step 2: Identify consequence of missing check

    Without checking, Order can contain items not on Menu, causing errors or confusion.
  3. Final Answer:

    Order may include items not available in the Menu -> Option C
  4. Quick Check:

    Missing validation = invalid items in Order [OK]
Hint: Always check Menu before adding items to Order [OK]
Common Mistakes:
  • Assuming automatic price updates
  • Thinking Order rejects items by default
  • Confusing system behavior with unrelated effects
5. How would you design the Order class to handle multiple orders from different customers simultaneously in a scalable restaurant system?
hard
A. Store all orders in a single list without identifiers
B. Keep orders only in memory without persistence
C. Allow only one order at a time to avoid conflicts
D. Use unique order IDs and store orders in a centralized database with concurrency control

Solution

  1. Step 1: Identify need for unique order tracking

    Each order must have a unique ID to distinguish between multiple customers' orders.
  2. Step 2: Ensure scalability and data integrity

    Storing orders in a centralized database with concurrency control allows multiple orders simultaneously without conflicts.
  3. Final Answer:

    Use unique order IDs and store orders in a centralized database with concurrency control -> Option D
  4. Quick Check:

    Unique IDs + concurrency = scalable order handling [OK]
Hint: Use unique IDs and concurrency-safe storage for multiple orders [OK]
Common Mistakes:
  • Ignoring concurrency issues
  • Using single list causing data overwrite
  • Not persisting orders leads to data loss