Food Delivery Application Using Design Patterns

This article will explain the design and development of a food delivery application by using different kinds of design patterns.

Problem Statement

Design an online order food delivery application catering to the following use cases:
  1. User can search different restaurants.
  2. User can select a restaurant.
  3. User can see menus.
  4. Restaurant can change the menu  
  5. User adds item for menu
  6. User orders the food
  7. User can track the order in real time.
  8. User can cancel the order
  9. User pays for the order

Solution

I have implemented  a food delivery application by using different types of design patterns. The below design patterns are involved according to module,
  1. User can search different restaurants Interpreter Design Pattern
  2. User sees Menu Iterator Pattern
  3. Adding food items for order Builder Design Pattern
  4. Order and Cancellation of food items Command Design Pattern
  5. Track an Order in Real Time Observer Pattern
I will explain the implementation of each module one by one but before that I want to show you a project dependency diagram for each module. Below is the dependency diagram.
 
                                         Food Delivery Application Module Dependencies 

Module 1 User can search different restaurants- (Interpreter Design Pattern)

The Interpreter Design Pattern specifies the way to evaluate or interpret expression in a language. It is very good in pattern matching. I have used this design pattern for the searching of different restaurants because the user searches based on location, name of restaurant, food items, PIN, etc. It forms a pattern. So, pattern implementation can be split into three different parts - the class definitions, the parser development and the expression evaluation.
 
Below is the "Code Map" diagram of the restaurant search based on location using Interpreter Design Pattern,
 
 
Module 2 User Sees Menu - Iterator Pattern
 
The Iterator Pattern provides a way to access elements of an aggregate object sequentially without exposing the underlying structure of the object. I have used this design pattern for the displaying of food menus based on the restaurant because different food items form a menu and the possibility of multiple traversals can be there and I don't want to expose its internal representation to the outside.

Below is the "Code Map" diagram of User Sees Menu based on restaurant Id or Name using Iterator Design Pattern,
 
 Module 3 Adding food items for ordering - Builder Design Pattern
 
The builder pattern is a creational design pattern used to configure and assemble complex objects. It provides a way to create the same object with different kinds of objects. I have used this design pattern for adding food items because different kinds of food items create one meal.
 
Below is the "Code Map" diagram of adding food items for ordering using Builder Design Pattern, 
 
Module 4 Order or Cancellation of Food or Meal - Command Design Pattern
 
Command design pattern falls under behavioral design pattern. It wraps the request under an object that is called Command. That command object is being passed to invoker object. I have used this design pattern because user can order or cancel food menus for delivery. Two different kinds of requests can be done by the user for food ordering.
 
Below is the "Code Map" diagram if user orders or cancels a meal after building the meal using Command Design Pattern, 


Module 5 Track an Order in Real Time - Observer Design Pattern
 
Observer design pattern is used in a situation where an object should be able to notify other objects about state change. I have used this pattern for the development of tracking an order in real time because whenever the food delivery states something like "food is packed for delivery, " "delivery boy is on the way," "It will be there in two minutes," "food delivered" or "food canceled,"  the user will be notified automatically.
 
Below is the "Code Map" diagram of Track an Order in Real Time after Ordering Meal using Observer Design Pattern, 


Code Implementation

I have attached the zipped code related to whole functionalities implementation. Pasting the whole code here is not possible because it is very large. So, here I will just add the execution entry point driver codes for the basic understanding of code flow of this project.
It is a console application because the main point is to make you understand the design approach for the development of any application.
  1. using FoodDeliveryApp.FoodDeliveryAppModel;  
  2. using FoodDeliveryApp.OrderAndCancellation;  
  3. using FoodDeliveryApp.Ordering;  
  4. using FoodDeliveryApp.RestaurantFoodMenu;  
  5. using FoodDeliveryApp.RestaurantSearch;  
  6. using FoodDeliveryApp.Tracking;  
  7. using System;  
  8. using System.Collections.Generic;  
  9. using System.Linq;  
  10. using System.Text;  
  11. using System.Threading.Tasks;  
  12. using System.Threading;  
  13. using FoodDeliveryApp.FoodDeliveryDriver;  
  14.   
  15. namespace FoodDeliveryApp  
  16. {  
  17.     class Program  
  18.     {  
  19.         static void Main(string[] args)  
  20.         {  
  21.  
  22.             #region User Searches Restaurant  
  23.   
  24.             //User Searches Restaurant.  
  25.             RestaurantSearchDriver restaurantSearchDriver = new RestaurantSearchDriver();  
  26.             var restaurantId = restaurantSearchDriver.RestaurantSearch();  
  27.  
  28.             #endregion  
  29.  
  30.             #region User Sees Food Menu  
  31.   
  32.             //User sees Food Menu Items based on the selected Restaurant Id.  
  33.             MealMenuIteratorDriver mealMenuIteratorDriver = new MealMenuIteratorDriver();  
  34.            var foodMenu = mealMenuIteratorDriver.PrintMealMenu(restaurantId);  
  35.  
  36.             #endregion  
  37.  
  38.             #region User Selects Meal  
  39.   
  40.             //Meal Selector.  
  41.             MealSelectorDriver mealSelectorDriver = new MealSelectorDriver();  
  42.             var selectedMealItems = mealSelectorDriver.MealSelectionbyUser(foodMenu);  
  43.  
  44.             #endregion  
  45.  
  46.             #region Restaurant Builds Meal  
  47.   
  48.             //Calling Meal Builder  
  49.             MealBuilderDriver mealBuilderDriver = new MealBuilderDriver();  
  50.             var totalCost = mealBuilderDriver.BuildMealForUser(selectedMealItems);  
  51.  
  52.             #endregion  
  53.  
  54.             #region User Orders Food  
  55.   
  56.             //Order Food  
  57.             string orderId = string.Empty;  
  58.             UserModel user = null;  
  59.             MealOrderDriver mealOrderDriver = new MealOrderDriver();  
  60.             var cancel = mealOrderDriver.MealOrderByUser(selectedMealItems, totalCost, restaurantId, out orderId, out user);  
  61.  
  62.             #endregion  
  63.  
  64.             #region User Tracks Order  
  65.   
  66.             //Order Tracking.  
  67.             OrderTrackingDriver orderTrackingDriver = new OrderTrackingDriver();  
  68.             orderTrackingDriver.OrderTrackingByUser(restaurantId, orderId, user, cancel);  
  69.  
  70.             #endregion  
  71.   
  72.             Console.ReadKey();  
  73.         }  
  74.     }  
  75. }  
Please find the complete code implementation in the zipped folder attached with this article.

Sequence Diagram based on the flow of application

 

Conclusion

Analysis before the development of any project is the important part. I have analyzed and divided the project into five different module parts based on functionalities. And then, I have identified different kinds of design patterns which fit on each module based on its functionality and behavior. Design pattern plays a very important role for the quality of code, loose coupling, re-usability, and maintainability. So, always go with design pattern before starting any module development.