Skip to main content

Design a Shopping Cart system

Problem Statement

Design a Shopping Cart system where users can browse products, add items to a cart, update quantities, and place orders. The system should ensure product stock consistency, calculate total price correctly, and generate an order after checkout.


Functional Requirements

  • Users should be able to view products
  • Users should be able to add/remove products from cart
  • Cart should maintain quantity for each product
  • System should calculate total price of cart
  • Users should be able to place an order from cart
  • Stock should be validated before checkout
  • Cart should be cleared after successful order

Objects Required

  • User
  • Product
  • Cart
  • CartItem
  • Order
  • OrderItem
  • ShoppingCartService
  • InventoryService

Product Class


public class Product {

    private String productId;
    private String name;
    private double price;

    public Product(String productId, String name, double price) {
        this.productId = productId;
        this.name = name;
        this.price = price;
    }

    public double getPrice() {
        return price;
    }

    public String getName() {
        return name;
    }
}

The constructor initializes a product with its id, name, and price.

The getPrice() method returns the product price for cart calculations.

The getName() method is used for displaying product information to the user.


CartItem Class


public class CartItem {

    private Product product;
    private int quantity;

    public CartItem(Product product, int quantity) {
        this.product = product;
        this.quantity = quantity;
    }

    public double getTotalPrice() {
        return product.getPrice() * quantity;
    }

    public void addQuantity(int qty) {
        this.quantity += qty;
    }

    public Product getProduct() {
        return product;
    }
}

The constructor creates a cart item by linking a product with its quantity.

The getTotalPrice() method calculates the total cost of that item based on quantity and product price.

The addQuantity() method increases the quantity when the same product is added again instead of creating duplicates.


Cart Class


import java.util.*;

public class Cart {

    private List items = new ArrayList<>();

    public void addProduct(Product product, int qty) {

        for (CartItem item : items) {
            if (item.getProduct().getName().equals(product.getName())) {
                item.addQuantity(qty);
                return;
            }
        }

        items.add(new CartItem(product, qty));
    }

    public void removeProduct(String productName) {

        items.removeIf(item ->
                item.getProduct().getName().equals(productName)
        );
    }

    public double getTotalAmount() {

        double total = 0;

        for (CartItem item : items) {
            total += item.getTotalPrice();
        }

        return total;
    }

    public List getItems() {
        return items;
    }

    public void clearCart() {
        items.clear();
    }
}

The cart maintains a list of cart items and handles all cart-related operations.

The addProduct() method adds a product to the cart. If the product already exists, it simply updates the quantity instead of duplicating entries.

The removeProduct() method removes a product from the cart based on its name.

The getTotalAmount() method calculates the final cart value by summing up all cart items.

The clearCart() method empties the cart after a successful order placement.


Order Class


import java.util.*;

public class Order {

    private String orderId;
    private List items;
    private double totalAmount;

    public Order(String orderId, List items) {
        this.orderId = orderId;
        this.items = new ArrayList<>(items);
        this.totalAmount = calculateTotal();
    }

    private double calculateTotal() {

        double sum = 0;

        for (CartItem item : items) {
            sum += item.getTotalPrice();
        }

        return sum;
    }

    public double getTotalAmount() {
        return totalAmount;
    }
}

The constructor creates an order from the final cart items.

The calculateTotal() method computes the final payable amount at the time of order creation to ensure consistency.

The getTotalAmount() method returns the final locked order amount.


InventoryService Class


import java.util.*;

public class InventoryService {

    private Map stock = new HashMap<>();

    public boolean isAvailable(Product product, int qty) {
        return stock.getOrDefault(product.getName(), 0) >= qty;
    }

    public void reduceStock(Product product, int qty) {
        stock.put(product.getName(),
                stock.getOrDefault(product.getName(), 0) - qty);
    }

    public void addStock(Product product, int qty) {
        stock.put(product.getName(),
                stock.getOrDefault(product.getName(), 0) + qty);
    }
}

The inventory service manages product stock levels in the system.

The isAvailable() method checks whether enough stock exists before checkout.

The reduceStock() method updates stock after a successful order placement.

The addStock() method is used when inventory is replenished.


ShoppingCartService Class


import java.util.*;

public class ShoppingCartService {

    private InventoryService inventoryService;

    public ShoppingCartService(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    public Order checkout(Cart cart) {

        for (CartItem item : cart.getItems()) {
            if (!inventoryService.isAvailable(item.getProduct(), item.getProduct().getPrice() == 0 ? 0 : 1)) {
                System.out.println("Product out of stock");
                return null;
            }
        }

        for (CartItem item : cart.getItems()) {
            inventoryService.reduceStock(item.getProduct(), 1);
        }

        Order order = new Order(UUID.randomUUID().toString(), cart.getItems());

        cart.clearCart();

        return order;
    }
}

The ShoppingCartService controls the checkout flow of the system.

The checkout() method first validates stock for all items. If any product is unavailable, the checkout is stopped.

After validation, it reduces inventory stock and creates a final order.

Finally, it clears the cart to complete the purchase cycle.


Main Class


public class Main {

    public static void main(String[] args) {

        Product p1 = new Product("P1", "Laptop", 50000);
        Product p2 = new Product("P2", "Phone", 20000);

        Cart cart = new Cart();

        cart.addProduct(p1, 1);
        cart.addProduct(p2, 2);

        InventoryService inventory = new InventoryService();
        inventory.addStock(p1, 10);
        inventory.addStock(p2, 10);

        ShoppingCartService service = new ShoppingCartService(inventory);

        Order order = service.checkout(cart);

        if (order != null) {
            System.out.println("Order placed successfully. Total: " + order.getTotalAmount());
        }
    }
}

The main method simulates a full shopping flow from adding products to checkout and order creation.


Class Diagram

UseruserId : Stringname : StringProductproductId : Stringname : Stringprice : doubleCartitems : List<CartItem>addProduct(Product, int) : voidremoveProduct(String) : voidgetTotalAmount() : doubleclearCart() : voidCartItemproduct : Productquantity : intgetTotalPrice() : doubleaddQuantity(int) : voidgetProduct() : ProductOrderorderId : Stringitems : List<CartItem>totalAmount : doubleInventoryServiceisAvailable(Product, int) : booleanreduceStock(Product, int) : voidaddStock(Product, int) : voidShoppingCartServicecheckout(Cart) : 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...