Skip to main content

Design a Food Delivery/Ordering System

Problem Statement

Design a food delivery system that allows customers to browse restaurants, place food orders, and track delivery status. The design should manage restaurant menus, order processing, and delivery assignment while ensuring that orders move through different states correctly.


Functional Requirements

  • The design should support multiple restaurants
  • Each restaurant should maintain its own menu items
  • Customers should be able to place food orders
  • An order can contain multiple food items
  • The system should calculate the total order amount
  • Orders should move through different statuses such as placed, preparing, and delivered
  • The design should support delivery partner assignment
  • The system should allow order tracking

Objects Required

  • Customer
  • Restaurant
  • MenuItem
  • Order
  • OrderStatus
  • DeliveryPartner
  • FoodDeliverySystem

OrderStatus Enum


public enum OrderStatus {
    PLACED,
    PREPARING,
    OUT_FOR_DELIVERY,
    DELIVERED
}

The OrderStatus enum represents the current stage of an order.

Using enums keeps the allowed states fixed and avoids invalid order status values.


MenuItem Class

The MenuItem class represents a food item available in a restaurant.


public class MenuItem {

    private String itemName;
    private double price;

    public MenuItem(String itemName,
                    double price) {

        this.itemName = itemName;
        this.price = price;
    }

    public double getPrice() {
        return price;
    }

    public String getItemName() {
        return itemName;
    }
}

The constructor initializes the food item with its name and price.

The getter methods are used while calculating order totals and displaying menu information.


Restaurant Class

The Restaurant class manages menu items offered by a restaurant.


import java.util.*;

public class Restaurant {

    private String restaurantName;
    private List<MenuItem> menu;

    public Restaurant(String restaurantName,
                      List<MenuItem> menu) {

        this.restaurantName = restaurantName;
        this.menu = menu;
    }

    public List<MenuItem> getMenu() {
        return menu;
    }

    public String getRestaurantName() {
        return restaurantName;
    }
}

The constructor initializes the restaurant name and its menu items.

The getMenu() method returns all food items available in the restaurant.


Customer Class

The Customer class stores customer related information.


public class Customer {

    private String customerId;
    private String customerName;

    public Customer(String customerId,
                    String customerName) {

        this.customerId = customerId;
        this.customerName = customerName;
    }

    public String getCustomerName() {
        return customerName;
    }
}

The constructor initializes customer details.

The getCustomerName() method is useful while displaying order details.


DeliveryPartner Class

The DeliveryPartner class represents the person assigned to deliver orders.


public class DeliveryPartner {

    private String partnerId;
    private String name;

    public DeliveryPartner(String partnerId,
                           String name) {

        this.partnerId = partnerId;
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

The constructor initializes the delivery partner details.

The getName() method is used while displaying delivery information.


Order Class

The Order class stores details related to a food order.


import java.util.*;

public class Order {

    private String orderId;
    private Customer customer;
    private Restaurant restaurant;
    private List<MenuItem> items;
    private OrderStatus status;
    private DeliveryPartner partner;

    public Order(String orderId,
                 Customer customer,
                 Restaurant restaurant,
                 List<MenuItem> items) {

        this.orderId = orderId;
        this.customer = customer;
        this.restaurant = restaurant;
        this.items = items;
        this.status = OrderStatus.PLACED;
    }

    public double calculateTotal() {

        double total = 0;

        for (MenuItem item : items) {
            total += item.getPrice();
        }

        return total;
    }

    public void assignDeliveryPartner(
            DeliveryPartner partner) {

        this.partner = partner;
    }

    public void updateStatus(OrderStatus status) {
        this.status = status;
    }
}

The constructor creates an order with customer, restaurant, and selected food items.

The order status is initially marked as PLACED.

The calculateTotal() method iterates through all ordered items and computes the total bill amount.

The assignDeliveryPartner() method associates a delivery partner with the order.

The updateStatus() method changes the order state as it moves through the delivery flow.


FoodDeliverySystem Class

The FoodDeliverySystem class coordinates restaurants and order processing.


import java.util.*;

public class FoodDeliverySystem {

    private List<Restaurant> restaurants;

    public FoodDeliverySystem(
            List<Restaurant> restaurants) {

        this.restaurants = restaurants;
    }

    public Order placeOrder(
            Customer customer,
            Restaurant restaurant,
            List<MenuItem> items) {

        Order order = new Order(
                UUID.randomUUID().toString(),
                customer,
                restaurant,
                items
        );

        System.out.println(
                "Order placed successfully"
        );

        return order;
    }
}

The constructor initializes the delivery platform with available restaurants.

The placeOrder() method creates a new order object with a unique order id.

Once the order is created, it is returned so that the caller can track or update it further.


Main Class

The Main class demonstrates the complete food ordering flow.


import java.util.*;

public class Main {

    public static void main(String[] args) {

        MenuItem pizza =
                new MenuItem("Pizza", 250);

        MenuItem burger =
                new MenuItem("Burger", 150);

        Restaurant restaurant =
                new Restaurant(
                        "Food Hub",
                        Arrays.asList(pizza, burger)
                );

        FoodDeliverySystem system =
                new FoodDeliverySystem(
                        Arrays.asList(restaurant)
                );

        Customer customer =
                new Customer("C1", "Prasanna");

        Order order = system.placeOrder(
                customer,
                restaurant,
                Arrays.asList(pizza, burger)
        );

        System.out.println(
                "Total Amount: "
                + order.calculateTotal()
        );

        DeliveryPartner partner =
                new DeliveryPartner(
                        "D1",
                        "Rahul"
                );

        order.assignDeliveryPartner(partner);

        order.updateStatus(
                OrderStatus.OUT_FOR_DELIVERY
        );

        order.updateStatus(
                OrderStatus.DELIVERED
        );

        System.out.println(
                "Order delivered successfully"
        );
    }
}

The main() method starts by creating menu items and a restaurant.

A customer places an order containing multiple food items.

The total amount is calculated using the order object.

A delivery partner is then assigned, and the order status is updated until delivery completion.


Class Diagram

OrderStatusPLACEDPREPARINGOUT_FOR_DELIVERYDELIVEREDMenuItemitemName : Stringprice : doublegetPrice() : doublegetItemName() : StringRestaurantrestaurantName : Stringmenu : List<MenuItem>getMenu() : List<MenuItem>getRestaurantName() : StringCustomercustomerId : StringcustomerName : StringgetCustomerName() : StringDeliveryPartnerpartnerId : Stringname : StringgetName() : StringOrderorderId : Stringcustomer : Customerrestaurant : Restaurantitems : List<MenuItem>status : OrderStatuspartner : DeliveryPartnercalculateTotal() : doubleassignDeliveryPartner(partner : DeliveryPartner) : voidupdateStatus(status : OrderStatus) : voidFoodDeliverySystemrestaurants : List<Restaurant> customer : Customer,restaurant : Restaurant,items : List<MenuItem>placeOrder() : OrderMainmain(args : String[]) : void

Also See

Comments

Popular posts from this blog

Designing a Parking Lot - Low Level Design

Problem Statement Design a parking lot that can handle vehicles entering and leaving while managing parking across multiple floors. Each vehicle should be assigned a suitable parking spot based on its type, and the spot should be freed once the vehicle exits. The design should also support generating a ticket at entry and optionally calculating the parking fee based on the duration of stay. Asked In Companies Amazon Google Microsoft Uber Walmart Flipkart Meta PayPal Oracle Salesforce Adobe Apple Intuit LinkedIn Atlassian Functional Requirements The design should support multiple vehicle types such as bikes, cars, and trucks A vehicle must be assigned a parking spot compatible with its type A parking spot cannot be assigned to more than one vehicle at a time The parking lot should support multiple levels (floors) The design should search and allocate an availa...

Most Frequently Asked Low Level Design(LLD) Interview Questions

Below are the curated list of most commonly asked Low Level Design (LLD) interview problems. Each problem includes a short description and a link to the complete solution with code and class diagrams. Design Parking Lot System The system should handle parking for different vehicle types such as bikes, cars, and trucks. It should manage slot allocation, availability tracking, and entry/exit flow. The design also ensures efficient usage of parking space under varying load conditions. View Solution Design Elevator / Lift System The system should support multiple elevators operating across floors with request handling logic. It focuses on scheduling algorithms to minimize wait time and optimize movement. It also manages direction control and concurrent floor requests. View Solution Design Movie Ticket Booking System The system should allow users to browse movies, select shows, and book seats. It handles seat ...

Software Design Patterns for LLD Interviews: A Complete Guide

Software Design Patterns for LLD Interviews: A Complete Guide In Software Development Engineer (SDE) interviews—especially for mid-level and senior roles—low-level design (LLD) rounds assess your ability to write clean, reusable, maintainable, and extensible code. The foundation of resolving these architectural challenges lies in the standard Gang of Four (GoF) Design Patterns. Rather than memorizing theoretical definitions, interviewers expect you to apply these patterns to real-world scenarios, identifying the trade-offs of each. Below is a comprehensive guide to the 12 most frequently asked design patterns in LLD interviews, categorized by their classification (Creational, Structural, and Behavioral). Each pattern contains a concrete, real-world Java implementation and a detailed breakdown of design decisions. Creational Design Patterns Creational design patterns deal with object creation mechanisms. They abstract the instantiation process, making a system independent of how...