Design a Restaurant Management System
OOP design for a restaurant management system covering table reservations, menu management, order processing, kitchen workflow, billing with split payments, and staff coordination.
The Problem
Your restaurant group manages 12 locations across a city. Each location still runs on paper tickets and a whiteboard for table status. Last Saturday night, a host seated a party of six at a table that was already reserved for 7:30 PM. The kitchen received duplicate orders because a waiter scribbled the same ticket twice. When the bill came, the party wanted to split by items, but the cashier spent 15 minutes doing mental math while a queue of eight tables waited to pay.
Restaurant management is harder than it looks because multiple workflows run in parallel. Tables cycle through reservation, seating, and cleaning. Orders flow from waiter to kitchen to table. The kitchen juggles dozens of items across different stations with varying prep times. Billing must handle single payments, equal splits, item-based splits, and custom splits, all while taxes and service charges apply consistently.
Design the core classes for a restaurant management system that handles table reservations, menu management, order processing with kitchen routing, table lifecycle tracking, billing with flexible split payments, and staff coordination through observer-based notifications.
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: "Is this dine-in only, or does the system need to support takeout and delivery as well?"
Interviewer: "Dine-in only for the initial design. Takeout and delivery are good extensibility topics."
Good. Dine-in only means every order is tied to a table, and the table lifecycle is central to the design. No need for a delivery subsystem.
You: "How does seating work? Do customers always have reservations, or do walk-ins happen too?"
Interviewer: "Both. Reservations guarantee a table at a specific time. Walk-ins get seated if a suitable table is available. If not, they wait."
Two paths to seating: reservation-based and walk-in. The table assignment logic needs to handle both. Reservations add a time dimension that walk-ins do not have.
You: "How should the system assign tables? Does the host just pick one, or should the system recommend the best fit?"
Interviewer: "The system should recommend. Consider party size relative to table capacity. Don't seat a couple at an eight-person table if a two-top is free."
Table assignment is a strategy problem. First-available is the naive approach. Optimizing by party size relative to capacity avoids wasting large tables on small parties.
You: "Does the kitchen operate as a single queue, or are there separate stations like grill, cold prep, and dessert?"
Interviewer: "Separate stations. Each menu item is tagged with a station. The kitchen display routes items to the correct station automatically."
Station-based routing means the system must split an order into sub-orders grouped by station. Each station works its queue independently.
You: "How does the kitchen signal that an item is ready? Does the waiter poll, or does the system push a notification?"
Interviewer: "Push notification. When the kitchen marks an item ready, the assigned waiter gets an alert. When all items for a table are ready, the waiter gets a 'serve now' alert."
Observer pattern. The kitchen publishes readiness events. Waiters subscribe to events for their assigned tables.
You: "What billing split options do customers need?"
Interviewer: "Four options: single bill for the whole table, split equally among N people, split by items where each person selects their items, and custom split where each person pays an arbitrary amount."
Four split strategies. Each produces a different set of payment amounts from the same order total. Strategy pattern with a common interface.
You: "Should the system handle tips and service charges?"
Interviewer: "Include a configurable service charge percentage. Tips are optional and added per payment. No automatic gratuity calculation."
Service charge is applied at the bill level before splitting. Tips are per-payment, added after the split.
You: "Do we need to track dietary restrictions or allergens on menu items?"
Interviewer: "Yes, each menu item should have a list of allergens. The system should be able to filter the menu by dietary restrictions, but no automatic order validation against customer allergies."
Allergens are metadata on menu items. Filtering is a read operation, not a constraint on ordering.
Perfect. You have clarified scope and ruled out unnecessary complexity. The core system is dine-in with reservations and walk-ins, station-based kitchen routing, observer notifications, and strategy-based billing splits.
Final Requirements
Functional Requirements:
- Manage a menu of categorized items, each with a price, description, station assignment, and allergen list
- Accept reservations for a specific date, time, and party size, and seat walk-ins when tables are available
- Assign tables using a configurable strategy that optimizes for party size vs. table capacity
- Process orders: waiter creates an order for a table, adds items, sends to kitchen
- Route kitchen orders to the correct station with priority ordering (appetizers before mains)
- Track table lifecycle through states: AVAILABLE, RESERVED, OCCUPIED, NEEDS_CLEANING
- Generate bills with four split strategies: single, equal split, by-item split, and custom split
- Notify waiters when kitchen items are ready and when all items for a course are complete
Non-Functional Requirements:
- Thread safety for concurrent table assignment and order processing
- Extensibility for new split strategies, table assignment algorithms, and kitchen station types
- Clean separation between order management, kitchen workflow, and billing logic
Out of Scope:
- UI rendering, REST API layer, and kitchen display hardware
- Database persistence and ORM mapping
- Takeout, delivery, and online ordering
- Inventory and ingredient tracking
- Payment gateway integration (assume a simple
PaymentServiceinterface) - Automatic allergen validation against customer profiles
30-Second Design Summary
Restaurant coordinates physical seating, reservations, orders, kitchen routing, and billing without owning every rule. Table and Order each have explicit lifecycles; KitchenOrder splits one waiter order by station; billing uses independent split strategies; and kitchen readiness is observed by staff-facing listeners. The core invariants are no double seating, no duplicate kitchen submission, and payments whose parts sum exactly to the bill total.
5-Minute Walkthrough
- Set the scope. The core covers reservations and walk-ins, table assignment, order and kitchen workflows, table/order states, bills, split payments, and notifications. Delivery, inventory, UI, and payment-provider internals are extensions.
- Separate physical and workflow objects.
Tableowns capacity/status,Reservationrepresents a future claim,Orderbelongs to a table, andKitchenOrderbelongs to a station.Billsummarizes the order;Paymentrepresents one contribution. - Seat a party. Check reservation/walk-in eligibility, choose a compatible available table through a strategy, and transition it atomically to the appropriate state.
- Send and complete an order. Add validated items, split them by station, enqueue prioritized kitchen work, and observe item/course completion without making the waiter order know station details.
- Close the bill. Calculate totals using a cent-precise split strategy, validate that all payment shares sum to the total, process payments, and close the table only after the bill is settled and cleanup is complete.
Example Inputs and Outputs
Scenario 1: Walk-in Seating and Order
- Input: Party of 4 arrives, no reservation. Waiter requests table assignment.
- Expected: System assigns a 4-top table (or smallest available table that fits 4). Table status changes from AVAILABLE to OCCUPIED. Waiter creates an order, adds 2 appetizers and 4 mains. Kitchen receives appetizer items routed to cold station, main items routed to grill station.
- Why: Validates table assignment strategy, order creation, and station-based routing.
Scenario 2: Reservation with Split Bill
- Input: Reservation for 6 at 7:30 PM. Party arrives, is seated. After dining, they request a split-by-items bill.
- Expected: System generates a bill with total including service charge. Each guest selects their items. System produces individual payment amounts. Each person pays their share plus optional tip.
- Why: Validates reservation flow, billing calculation, and item-based split strategy.
Scenario 3: Kitchen Notification Flow
- Input: Order with 3 appetizers (cold station) and 3 mains (grill station) is sent to kitchen. Cold station finishes appetizers.
- Expected: System notifies the assigned waiter that appetizers are ready to serve. Grill station continues working on mains. When mains are done, waiter gets a second notification.
- Why: Validates observer-based kitchen notifications and per-station tracking.
Try It Yourself
Try it yourself
Before reading the solution, spend 20 minutes sketching your own class diagram. Focus on the table lifecycle, how orders flow to the kitchen, and how billing splits work. Identify where State, Strategy, and Observer patterns naturally fit. Compare your approach with the walkthrough below.
Step 1: Identify Core Entities
Start by asking: what are the main "things" in this problem? Look for nouns in your requirements. A restaurant system has physical entities (tables, kitchens), people (staff, customers), workflows (orders, reservations), and financial objects (bills, payments).
A common mistake is stuffing everything into a single Restaurant god class. Good design means each class has a single, clear job. The restaurant orchestrates, but it does not contain order logic, kitchen routing, or billing math.
| Entity | Responsibility | Key attributes |
|---|---|---|
| Restaurant | Top-level orchestrator. Holds tables, menu, and staff. Delegates to services. | name, tables, menu, staff |
| Table | Physical seating unit. Tracks status and capacity. | tableNumber, capacity, status |
| Reservation | A future commitment to hold a table. Links customer, table, date, time, and party size. | customer, table, dateTime, partySize, status |
| MenuItem | A single dish or drink on the menu. Belongs to a category and a kitchen station. | name, price, category, station, allergens |
| MenuCategory | Groups related menu items (Appetizers, Mains, Desserts, Drinks). | name, items |
| Order | A collection of items requested by a table. Tracks lifecycle state. | table, items, waiter, status, createdAt |
| OrderItem | A single line in an order: one menu item with quantity and customization notes. | menuItem, quantity, notes |
| KitchenOrder | A subset of order items routed to a specific kitchen station. | station, items, status, priority |
| Bill | Financial summary for an order. Holds subtotal, service charge, tax, and total. | order, subtotal, serviceCharge, tax, total |
| Payment | A single payment toward a bill. One bill may have multiple payments (split). | bill, amount, tip, method |
| Staff | Abstract base for restaurant employees. Specialized into Waiter, Chef, Manager. | name, role, id |
| Customer | A person dining or making a reservation. | name, phone, email |
Notice that Bill and Payment are separate because one bill can have multiple payments (split scenarios). If you merged them, you could not represent "three people each paying their share of one bill." That separation is the key domain insight.
Step 2: Define Relationships and Class Design
Class Diagram
Key Class Interfaces
Order: The Central Workflow Object
An Order is the spine of the system. It connects a table to its food, tracks lifecycle state, and splits into kitchen orders for station routing.
Deriving state from requirements:
| Requirement | What Order must track |
|---|---|
| "Waiter creates an order for a table" | The table and the waiter who created it |
| "Adds items, sends to kitchen" | List of OrderItems, lifecycle status |
| "Track order lifecycle" | OrderStatus enum (PLACED through CLOSED) |
| "Route to correct station" | Ability to group items by station |
Deriving methods from needs:
| Need from requirements | Method |
|---|---|
| "Waiter adds items to order" | addItem(menuItem, quantity, notes) |
| "Sends order to kitchen" | sendToKitchen() returns List of KitchenOrders |
| "Kitchen marks items ready" | Tracked via KitchenOrder status |
| "All items served" | markServed() |
| "Generate bill" | Via BillingService, not on Order itself |
Table: The Physical Resource
A Table represents a physical seating unit. Its status drives availability for reservations and walk-ins.
Deriving state from requirements:
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with SDEpedia Premium.