Determine the different ways the system will be used. This includes main functions the system needs to perform and who will use it.
1) system should allow users to open an account and register themselves as delivery partner or user
2) System should manage menus of different resturants
3) System should allow users to place order
4) System should allow delivery partner to accept or reject the current order
5) Allow users to provide Rating and Reviews for their order
Based on the requirements and use cases, identify the main objects of the system...
Account -> User ,delivery partner Restaurants Order Cordinates Payment,Rating Reviews,Menu
and Items
Determine how these objects will interact with each other to fulfill the use cases...
Account
Inheritance:
User and DeliveryPartner extend Account.
Responsibilities:
Represents the base class for accounts in the system.
Stores common properties such as firstName, lastName, and phoneNo.
2. User
Is-a Relationship:
User is an Account.
Responsibilities:
Represents users who place orders in the system.
May interact with restaurants and orders.
3. DeliveryPartner
Is-a Relationship:
DeliveryPartner is an Account.
Responsibilities:
Represents delivery personnel.
Responsible for accepting or rejecting assigned orders.
4. Restaurant
Has-a Relationship:
A Restaurant has a Menu.
A Restaurant has RatingsReviews (for storing feedback from users).
Responsibilities:
Represents restaurants in the system.
Provides menu items for users to order.
5. Menu
Has-a Relationship:
A Menu has a list of MenuItem.
Responsibilities:
Represents the menu of a restaurant.
6. MenuItem
Part-of Relationship:
A MenuItem is part of a Menu.
Responsibilities:
Represents individual items on the menu.
Stores item details like name and price.
7. Order
Has-a Relationship:
An Order has a list of OrderItem.
An Order is linked to a User (who placed it).
An Order is linked to a Restaurant (from which it was placed).
Responsibilities:
Represents an order placed by a user.
Contains details about ordered items and the restaurant.
8. OrderItem
Part-of Relationship:
An OrderItem is part of an Order.
Responsibilities:
Represents individual items in an order.
Contains details like itemName and quantity.
9. RatingsReviews
Has-a Relationship:
RatingsReviews is associated with Restaurant and Order.
Responsibilities:
Stores user feedback (rating and review) for restaurants.
10. Payment
Interface:
Payment is implemented by PaymentCheque, PaymentCreditCard, and PaymentUPI.
Responsibilities:
Provides a common interface for payment processing.
Each implementation represents a specific payment method.
11. Cordinates
Association:
Used by Restaurant and possibly DeliveryPartner to represent geographical location.
Responsibilities:
Represents GPS coordinates for delivery and restaurant location tracking.
Design inheritance trees where applicable to promote code reuse and polymorphism. This step involves identifying common attributes and behaviors that can be abstracted into parent classes...
Account
Inheritance:
User and DeliveryPartner extend Account.
Responsibilities:
Represents the base class for accounts in the system.
Stores common properties such as firstName, lastName, and phoneNo.
2. User
Is-a Relationship:
User is an Account.
Responsibilities:
Represents users who place orders in the system.
May interact with restaurants and orders.
3. DeliveryPartner
Is-a Relationship:
DeliveryPartner is an Account.
Responsibilities:
Represents delivery personnel.
Responsible for accepting or rejecting assigned orders.
4. Restaurant
Has-a Relationship:
A Restaurant has a Menu.
A Restaurant has RatingsReviews (for storing feedback from users).
Responsibilities:
Represents restaurants in the system.
Provides menu items for users to order.
5. Menu
Has-a Relationship:
A Menu has a list of MenuItem.
Responsibilities:
Represents the menu of a restaurant.
6. MenuItem
Part-of Relationship:
A MenuItem is part of a Menu.
Responsibilities:
Represents individual items on the menu.
Stores item details like name and price.
7. Order
Has-a Relationship:
An Order has a list of OrderItem.
An Order is linked to a User (who placed it).
An Order is linked to a Restaurant (from which it was placed).
Responsibilities:
Represents an order placed by a user.
Contains details about ordered items and the restaurant.
8. OrderItem
Part-of Relationship:
An OrderItem is part of an Order.
Responsibilities:
Represents individual items in an order.
Contains details like itemName and quantity.
9. RatingsReviews
Has-a Relationship:
RatingsReviews is associated with Restaurant and Order.
Responsibilities:
Stores user feedback (rating and review) for restaurants.
10. Payment
Interface:
Payment is implemented by PaymentCheque, PaymentCreditCard, and PaymentUPI.
Responsibilities:
Provides a common interface for payment processing.
Each implementation represents a specific payment method.
11. Cordinates
Association:
Used by Restaurant and possibly DeliveryPartner to represent geographical location.
Responsibilities:
Represents GPS coordinates for delivery and restaurant location tracking.
Consider using design patterns (e.g., Factory, Singleton, Observer, Strategy) that fit the problem...
For users and driver we are using factory design pattern
For payement we are using strategy pattern for different payment strategies like payment by card, cheque and upi
We can also use singelton pattern for each of the service which we have created
Attributes: For each class, define the attributes (data) it will hold...
Methods: Define the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation.
// File: Main.java
import models.;
import service.;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // Shared Scanner instance for the program
ExecutorService executorService = Executors.newFixedThreadPool(4); // Fixed thread pool with 4 threads
try {
OrderService orderService = new OrderService();
AccountService accountService = new AccountService();
RestaurantService restaurantService = new RestaurantService();
RestaurantRatingService restaurantRatingService = new RestaurantRatingService();
DeliveryPartnerAssignmentService deliveryPartnerAssignmentService = new DeliveryPartnerAssignmentService();
List<Account> deliveryPartners = new ArrayList<>();
List<Restaurant> restaurants = new ArrayList<>();
List<Order> orders = new ArrayList<>();
while (true) {
System.out.println("1-> Add a delivery Partner ");
System.out.println("2-> Add a restaurant");
System.out.println("3-> Create Order");
System.out.println("4-> Exit");
String input = scanner.nextLine().trim();
try {
int type = Integer.parseInt(input);
if (type == 1) {
executorService.submit(() -> {
Account deliveryPartner = accountService.createAccount(scanner);
synchronized (deliveryPartners) {
if (deliveryPartner != null) {
deliveryPartners.add(deliveryPartner);
System.out.println("Delivery partner added successfully.");
} else {
System.out.println("Failed to add delivery partner.");
}
}
});
} else if (type == 2) {
executorService.submit(() -> {
Restaurant restaurant = restaurantService.createRestaurant(scanner);
synchronized (restaurants) {
if (restaurant != null) {
restaurants.add(restaurant);
System.out.println("Restaurant added successfully.");
} else {
System.out.println("Failed to add restaurant.");
}
}
});
} else if (type == 3) {
if (restaurants.isEmpty()) {
System.out.println("No restaurants available. Please add a restaurant first.");
continue;
}
synchronized (restaurants) {
for (int i = 0; i < restaurants.size(); i++) {
System.out.println((i + 1) + "-> " + restaurants.get(i).getName());
}
}
System.out.println("Select the restaurant by number:");
String restaurantInput = scanner.nextLine().trim();
int index = Integer.parseInt(restaurantInput);
if (index < 1 || index > restaurants.size()) {
System.out.println("Invalid restaurant selection.");
continue;
}
Restaurant restaurant = restaurants.get(index - 1);
executorService.submit(() -> {
Order order = orderService.createOrder(restaurant, scanner);
restaurantRatingService.makeRestaurantReview(restaurant, scanner);
synchronized (deliveryPartners) {
deliveryPartnerAssignmentService.AssignDeliveryPartner(order, deliveryPartners);
}
});
} else if (type == 4) {
System.out.println("Exiting...");
break;
} else {
System.out.println("Invalid choice. Please enter a number between 1 and 4.");
}
} catch (NumberFormatException e) {
System.out.println("Invalid input. Please enter a valid number.");
}
}
} finally {
scanner.close();
executorService.shutdown(); // Shut down ExecutorService
System.out.println("Program terminated.");
}
}
}
// File: Account.java
package models;
public abstract class Account
{
String firstName;
String lastName;
long phoneNo;
Account(String firstName,String lastName,long phoneNo)
{
this.firstName=firstName;
this.lastName=lastName;
this.phoneNo=phoneNo;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public long getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(long phoneNo) {
this.phoneNo = phoneNo;
}
}
// File: Cordinates.java
package models;
public class Cordinates
{
int latitudes;
int longitudes;
public int getLatitudes() {
return latitudes;
}
public void setLatitudes(int latitudes) {
this.latitudes = latitudes;
}
public int getLongitudes() {
return longitudes;
}
public void setLongitudes(int longitudes) {
this.longitudes = longitudes;
}
public Cordinates(int latitudes, int longitudes) {
this.latitudes = latitudes;
this.longitudes = longitudes;
}
}
// File: DeliveryPartner.java
package models;
import java.util.ArrayList;
import java.util.List;
public class DeliveryPartner extends Account
{
public DeliveryPartner(String firstName, String lastName, long phoneNo) {
super(firstName, lastName, phoneNo);
}
}
// File: Menu.java
package models;
import java.util.List;
public class Menu
{
List<MenuItem> menuItems;
public Menu(List<MenuItem> menuItems) {
this.menuItems = menuItems;
}
public List<MenuItem> getMenuItems() {
return menuItems;
}
public void setMenuItems(List<MenuItem> menuItems) {
this.menuItems = menuItems;
}
}
// File: MenuItem.java
package models;
public class MenuItem
{
String name;
int cost;
public MenuItem(String name, int cost) {
this.name = name;
this.cost = cost;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
}
// File: Order.java
package models;
import java.util.List;
public class Order
{
List<OrderItem>orderItems;
int cost;
public Order(List<OrderItem> orderItems, int cost) {
this.orderItems = orderItems;
this.cost = cost;
}
public List<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(List<OrderItem> orderItems) {
this.orderItems = orderItems;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
}
// File: OrderItem.java
package models;
public class OrderItem
{
MenuItem menuItem;
int quantity;
public OrderItem(MenuItem menuItem, int quantity) {
this.menuItem = menuItem;
this.quantity = quantity;
}
public MenuItem getMenuItem() {
return menuItem;
}
public void setMenuItem(MenuItem menuItem) {
this.menuItem = menuItem;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
// File: Payment.java
package models;
public interface Payment
{
void makePayment(int cost);
}
// File: PaymentCheque.java
package models;
public class PaymentCheque implements Payment
{
@Override
public void makePayment(int cost)
{
System.out.println("Payment of "+cost+"Completed through cheque");
}
}
// File: PaymentCreditCard.java
package models;
public class PaymentCreditCard implements Payment {
@Override
public void makePayment(int cost)
{
System.out.println("Payment of "+cost+"completed through credit card");
}
}
// File: PaymentUPI.java
package models;
public class PaymentUPI implements Payment
{
@Override
public void makePayment(int cost)
{
System.out.println("Payment of rs"+cost+" completed through UPI");
}
}
// File: RatingsReviews.java
package models;
public class RatingsReviews
{
int rating;
String review;
public RatingsReviews(int rating, String review) {
this.rating = rating;
this.review = review;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
}
// File: Restaurant.java
package models;
import java.util.ArrayList;
import java.util.List;
public class Restaurant
{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Menu menu;
List<RatingsReviews> ratingsReviews;
List<Order >historyOrders;
public Menu getMenu() {
return menu;
}
public void setMenu(Menu menu) {
this.menu = menu;
}
public List<RatingsReviews> getRatingsReviews() {
return ratingsReviews;
}
public void setRatingsReviews(List<RatingsReviews> ratingsReviews) {
this.ratingsReviews = ratingsReviews;
}
public List<Order> getHistoryOrders() {
return historyOrders;
}
public Restaurant(String name,Menu menu) {
this.menu = menu;
this.name=name;
this.ratingsReviews = new ArrayList<>();
this.historyOrders =new ArrayList<>();
}
public void setHistoryOrders(List<Order> historyOrders) {
this.historyOrders = historyOrders;
}
}
// File: User.java
package models;
import java.util.List;
public class User extends Account
{
List<Order>orderList;
public List<Order> getOrderList() {
return orderList;
}
public void setOrderList(List<Order> orderList) {
this.orderList = orderList;
}
public User(String firstName, String lastName, long phoneNo) {
super(firstName, lastName, phoneNo);
}
}
// File: AccountService.java
package service;
import models.Account;
import models.DeliveryPartner;
import models.User;
import java.util.InputMismatchException;
import java.util.Scanner;
public class AccountService {
public synchronized Account createAccount(Scanner scanner) {
try {
System.out.println("Enter the type (User/DeliveryPartner), firstName, lastName, and phoneNo:");
String type = scanner.nextLine().trim();
String firstName = scanner.nextLine().trim();
String lastName = scanner.nextLine().trim();
long phoneNo;
// Validate input for phone number
if (!scanner.hasNextLong()) {
System.out.println("Invalid phone number. Please enter a valid number.");
scanner.nextLine().trim(); // Clear invalid input
return null;
}
phoneNo = scanner.nextLong();
// Create the appropriate account type
if (type.equalsIgnoreCase("User")) {
return new User(firstName, lastName, phoneNo);
} else if (type.equalsIgnoreCase("DeliveryPartner")) {
return new DeliveryPartner(firstName, lastName, phoneNo);
} else {
System.out.println("Invalid account type. Please enter either 'User' or 'DeliveryPartner'.");
return null;
}
} catch (InputMismatchException e) {
System.out.println("Invalid input format: " + e.getMessage());
scanner.nextLine().trim(); // Clear invalid input
} catch (Exception e) {
System.out.println("An unexpected exception occurred: " + e.getMessage());
}
return null;
}
}
// File: DeliveryPartnerAssignmentService.java
package service;
import models.Account;
import models.DeliveryPartner;
import models.Order;
import models.User;
import javax.swing.event.DocumentEvent;
import java.security.DigestException;
import java.util.List;
import java.util.Random;
public class DeliveryPartnerAssignmentService
{
public synchronized Account AssignDeliveryPartner(Order order, List<Account>deliveryPartner)
{
Random random=new Random();
int no=random.nextInt(deliveryPartner.size());
Account deliveryPartner1= deliveryPartner.get(no);
System.out.println("Deleivery partner"+deliveryPartner1.getFirstName()+" "+deliveryPartner1.getLastName()+" has been assigned");
return deliveryPartner1;
}
}
// File: OrderService.java
package service;
import models.*;
import javax.xml.catalog.Catalog;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Logger;
public class OrderService
{
Logger logger =Logger.getLogger("console");
public synchronized Order createOrder(Restaurant restaurant,Scanner scanner)
{
List<OrderItem>order=new ArrayList<>();
try
{
int cost=0;
List<MenuItem>menuItems=restaurant.getMenu().getMenuItems();
while(true)
{
System.out.println("Press 0 to exit");
System.out.println("Select the item and the quantiy of the item");
int index=1;
for(MenuItem menuItem:menuItems)
{
System.out.println(index+" "+menuItem.getName()+" "+menuItem.getCost());
index++;
}
int type=scanner.nextInt();
if(type==0)
{
break;
}
int quantity=scanner.nextInt();
if(type==0||quantity==0)
{
break;
}
order.add(new OrderItem(menuItems.get(type-1),quantity));
cost+=menuItems.get(type-1).getCost()*quantity;
}
System.out.println("Order placed successfully and order cost is "+cost);
Order finalOrder=new Order(order,cost);
return finalOrder;
}
catch (Exception e)
{
System.out.println("Exception occurred while placing the order"+e.getMessage());
}
return null;
}
}
// File: RestaurantRatingService.java
package service;
import models.RatingsReviews;
import models.Restaurant;
import java.net.SocketTimeoutException;
import java.util.Scanner;
public class RestaurantRatingService
{
public synchronized void makeRestaurantReview(Restaurant restaurant,Scanner scanner)
{
System.out.println("Enter the rating and review for the restaurant"+restaurant.getName());
try
{
int rating=scanner.nextInt();
String review=scanner.nextLine();
RatingsReviews ratingsReviews=new RatingsReviews(rating,review);
restaurant.getRatingsReviews().add(ratingsReviews);
// return ratingsReviews;
}
catch (Exception e)
{
System.out.println("Exception while adding rating or review for the restaurant");
}
}
}
// File: RestaurantService.java
package service;
import models.Menu;
import models.MenuItem;
import models.Restaurant;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class RestaurantService
{
public synchronized Restaurant createRestaurant(Scanner scanner)
{
try
{
System.out.println("Enter the name of the restaurant");
String restaurantName=scanner.nextLine();
System.out.println("Enter the number of items");
int no=Integer.parseInt(scanner.nextLine().trim());
List<MenuItem>menuItems=new ArrayList<>();
while(no-->0)
{
System.out.println("Enter the itemName and it's price");
String name=scanner.nextLine().trim();
int price=Integer.parseInt(scanner.nextLine().trim());
MenuItem menuItem=new MenuItem(name,price);
menuItems.add(menuItem);
}
Menu menu=new Menu(menuItems);
return new Restaurant(restaurantName,menu);
}
catch(Exception e)
{
System.out.println("Exception while creating a restaurant");
e.printStackTrace();
}
return null;
}
}
Check and explain whether your design adheres to solid principles (Ask interviewer what SOLID principle is if you can not recall it.)...
Single Responsibility Principle -> Each class is having only single responsibility so the design is following single responsibility principle
Open and closed principle -> Class like account were extended instead of making changes in exisiting classess
Liskov substitution principle -> Subclasses like user and delivery partner can easliy be substituted in place of parent class
Interface segration principle -> classes which implement payment interface only implement a single method
Explain how your design can handle changes in scale and whether it would be easily to extend with new functionalities...
Design is easily scalalbe as we are following solid principles.
Try creating a class, flow, state and/or sequence diagram using the diagramming tool. Mermaid flow diagrams can be used to represent system use cases. You can ask the interviewer bot to create a starter diagram if unfamiliar with the tool. Briefly explain your diagrams if necessary...
Added Class Diagram
Critically examine your design for any flaws or areas for future improvement...