System Design
Object-Oriented Design
Online Shopping System

Design Example: Online Shopping System

An Online Shopping System (like Amazon or eBay) manages a massive inventory of products, handles complex order lifecycles, and integrates multiple payment and shipping providers.


Step 1: Requirements Gathering

Core Use Cases:

  • Search: Customers can search for products by name, category, or tags.
  • Cart: Add/remove products and adjust quantities.
  • Checkout: Place an order, calculate taxes, and select shipping.
  • Payment: Support multiple payment methods (Credit Card, PayPal).
  • Order Tracking: Track status (Pending, Shipped, Delivered, Canceled).
  • Reviews: Customers can rate and review delivered products.
  • Admin: Manage inventory (Add/Remove products).

Account Types:

  • Guest: Can search and view products.
  • Member: Can place orders and leave reviews.
  • Admin: Can modify the catalog and manage users.

Step 2: Identify Core Objects

  • Product: Metadata like Name, Description, Price.
  • ProductItem: A specific inventory unit (handling stock levels).
  • ShoppingCart: Container for items before checkout.
  • Item: Represents a quantity of a specific product in a cart/order.
  • Order: Represents a completed transaction with a status and log.
  • Payment: Abstract base for payment processing.
  • Account: User information and roles.

Step 3: Design Class Diagram


Step 4: Implementation in TypeScript

enum OrderStatus { PENDING, SHIPPED, DELIVERED, CANCELED }
 
class Product {
  constructor(
    public id: string,
    public name: string,
    public price: number
  ) {}
}
 
class Item {
  constructor(
    public product: Product,
    public quantity: number
  ) {}
}
 
class ShoppingCart {
  private items: Item[] = [];
 
  public addItem(item: Item) {
    this.items.push(item);
  }
 
  public getTotal(): number {
    return this.items.reduce((sum, item) => sum + (item.product.price * item.quantity), 0);
  }
}
 
interface PaymentStrategy {
  pay(amount: number): boolean;
}
 
class CreditCardPayment implements PaymentStrategy {
  pay(amount: number) {
    console.log(`Paid ${amount} via Credit Card.`);
    return true;
  }
}

Deep Dive: Strategy Pattern for Payments

The Strategy Pattern allows the checkout process to remain agnostic of the specific payment method used. Adding a new provider (e.g., Apple Pay) simply requires a new strategy implementation.


Wrap Up

Designing an online shopping system is a masterclass in Decoupling. The catalog should not depend on the order logic, and the checkout process should be isolated from specific payment or shipping implementations.

[!IMPORTANT] Always implement Inventory Reservation during the checkout flow to prevent multiple customers from purchasing the same "last item" in stock.