Determine the different ways the system will be used. This includes main functions the system needs to perform and who will use it.
1) Track Stock levels in real time and update in case we recieve orders.
2) Provide Store Location Tracking
3) Create update and delete orders
4) Track incoming and upcoming shipments and provide shipment information
5) Manage User Roles and permissions
Based on the requirements and use cases, identify the main objects of the system...
The main objects are Stock which will have the high level details of a stock and each Stock will have many stock item which will have unique details like the barcode and few unique values to distinguish it from other stocks.
2) Storage class which will store the rack and other locations of each item
3) Order class that will store the the items which user wants
4) Shipment class it will store the different stockItems
5) User and Admin class for storing user and admin related information
Determine how these objects will interact with each other to fulfill the use cases...
Stock - > Each Stock class will be an abstract class and will have a barcode number that will assign barcode number to stock Item.
Stock Item -> Each Stock Item class will inherit the stock class and will implement the barcode method for setting up the bar code
Shipment-> The shipment class will have many stock Items which will be delivered to the warehouse
Order -> Each Order will have one or more stockItem that user will order
Account -> This class will store the general details like the userName, lastName phone number
User and Admin will be inheriting this class and user will make the order and admin will perform admin releated task
Rack -> Each Stock Item will have a rack position
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...
Stock - > Each Stock class will be an abstract class and will have a barcode number that will assign barcode number to stock Item.
Stock Item -> Each Stock Item class will inherit the stock class and will implement the barcode method for setting up the bar code
Shipment-> The shipment class will have many stock Items which will be delivered to the warehouse
Order -> Each Order will have one or more stockItem that user will order
Account -> This class will store the general details like the userName, lastName phone number
User and Admin will be inheriting this class and user will make the order and admin will perform admin releated task
Rack -> Each Stock Item will have a rack position
WareHouse Class -> This class will keep track of all the orders, shipments and stockItems
Consider using design patterns (e.g., Factory, Singleton, Observer, Strategy) that fit the problem...
We will be using singelton design pattern for creating single instance of warehouse
Factory Pattern for For different Stock Items we will be using this pattern
Strategy -> Different strategies of placing product on the rack will be implementd using this pattern.
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.
import java.util.ArrayList;
import java.util.List;
// Abstract Stock class
abstract class Stock {
private String barcode;
public String getBarcode() {
return barcode;
}
public void setBarcode(String barcode) {
this.barcode = barcode;
}
}
// StockItem class inheriting Stock
class StockItem extends Stock {
private String name;
private Rack rack;
public StockItem(String name, String barcode, Rack rack) {
this.name = name;
this.setBarcode(barcode);
this.rack = rack;
}
public String getName() {
return name;
}
public Rack getRack() {
return rack;
}
}
// Rack class representing the position of StockItem
class Rack {
private String rackPosition;
public Rack(String rackPosition) {
this.rackPosition = rackPosition;
}
public String getRackPosition() {
return rackPosition;
}
}
// Shipment class containing a list of StockItems
class Shipment {
private List<StockItem> stockItems;
public Shipment(List<StockItem> stockItems) {
this.stockItems = stockItems;
}
public List<StockItem> getStockItems() {
return stockItems;
}
}
// Order class containing one or more StockItems
class Order {
private List<StockItem> stockItems;
public Order(List<StockItem> stockItems) {
this.stockItems = stockItems;
}
public List<StockItem> getStockItems() {
return stockItems;
}
}
// Account class storing general user details
class Account {
private String userName;
private String lastName;
private String phoneNumber;
public Account(String userName, String lastName, String phoneNumber) {
this.userName = userName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
public String getUserName() {
return userName;
}
public String getLastName() {
return lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
}
// User class inheriting from Account
class User extends Account {
public User(String userName, String lastName, String phoneNumber) {
super(userName, lastName, phoneNumber);
}
public void makeOrder(Order order) {
// Logic to place an order
System.out.println("Order placed: " + order.getStockItems().size() + " items");
}
}
// Admin class inheriting from Account
class Admin extends Account {
public Admin(String userName, String lastName, String phoneNumber) {
super(userName, lastName, phoneNumber);
}
public void performAdminTask() {
// Logic for admin tasks
System.out.println("Admin tasks performed");
}
}
// Singleton WareHouse class
class WareHouse {
private static WareHouse instance;
private List<Order> orders;
private List<Shipment> shipments;
private List<StockItem> stockItems;
// Private constructor to prevent instantiation from other classes
private WareHouse() {
orders = new ArrayList<>();
shipments = new ArrayList<>();
stockItems = new ArrayList<>();
}
// Public method to provide access to the singleton instance
public static synchronized WareHouse getInstance() {
if (instance == null) {
instance = new WareHouse();
}
return instance;
}
public void addOrder(Order order) {
orders.add(order);
}
public void addShipment(Shipment shipment) {
shipments.add(shipment);
stockItems.addAll(shipment.getStockItems());
}
public List<Order> getOrders() {
return orders;
}
public List<Shipment> getShipments() {
return shipments;
}
public List<StockItem> getStockItems() {
return stockItems;
}
}
// Main class to test the functionality
public class Main {
public static void main(String[] args) {
// Creating a Rack
Rack rack1 = new Rack("A1");
// Creating StockItems
StockItem item1 = new StockItem("Item1", "123456", rack1);
StockItem item2 = new StockItem("Item2", "654321", rack1);
// Creating a Shipment
List<StockItem> shipmentItems = new ArrayList<>();
shipmentItems.add(item1);
shipmentItems.add(item2);
Shipment shipment = new Shipment(shipmentItems);
// Adding Shipment to WareHouse
WareHouse wareHouse = WareHouse.getInstance();
wareHouse.addShipment(shipment);
// Creating an Order
List<StockItem> orderItems = new ArrayList<>();
orderItems.add(item1);
Order order = new Order(orderItems);
// Adding Order to WareHouse
wareHouse.addOrder(order);
// Creating a User and placing an order
User user = new User("John", "Doe", "1234567890");
user.makeOrder(order);
// Creating an Admin and performing admin tasks
Admin admin = new Admin("Admin", "User", "0987654321");
admin.performAdminTask();
}
}
Check and explain whether your design adheres to solid principles (Ask interviewer what SOLID principle is if you can not recall it.)...
1) Single Responsibility Principle - > Each class whether it's a has only one responsibility
2) Open Closed Principle -> We have created new subclasses instead of extending the existing class
3) Liskov Substitution Priciple -> Subclass like Stock and User can be replaced by their subclass like Account can be replaced by the user and admin class
4) Inteface Segration Principle -> We have segreated the methods in differnt interfaces so classes don't have to implement unnecessary methods
5) Dependency Inversion principle in the warehouse managment calss the dependency inversion is followed where it is not tightly coupled
Explain how your design can handle changes in scale and whether it would be easily to extend with new functionalities...
1) The design is easily scalable by extending classes or implementing interface
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...