Bird
Raised Fist0

Order Management System

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
🏗️
Order Management System
Design an Order Management System managing order lifecycle states from Placed to Delivered
mediumSystems with State MachinesFreq: high
Prerequisites:OOP BasicsFinite State Machines
⚙️
Functional Requirements
  • Track order state transitions with validation
  • Allow cancellation only before shipment
  • Notify actors on state changes
  • Support concurrent updates to order state
  • Persist order details and state
  • Provide order status query API
  • Handle payment success and failure events
👤
Use Cases
  • Customer places an order
  • Order transitions through states: Placed, Confirmed, Packed, Shipped, Delivered
  • Order cancellation before shipment
  • Query order status
  • Handle payment confirmation
  • Handle failed delivery and retry
🧑‍💻
Actors
  • Customer
  • Order Processing System
  • Warehouse
  • Delivery Agent
  • Payment Gateway
❓
Clarifying Questions to Ask
  • How many concurrent threads can update the same order state? (Concurrency level)
  • Is there a pricing strategy affecting order state transitions or cancellations?
  • What happens if a state transition fails midway? Is rollback required?
  • Are partial shipments or split deliveries supported?
  • Should the system support retrying failed deliveries automatically?
Out of Scope
✗ Inventory management
✗ Payment processing internals
✗ User authentication and authorization
✗ UI/UX design
⚡
QPS Calculation
read qps5000
write qps1000
🖥️
Server Estimate
5
Estimated based on expected user base and order volume; 5 servers to handle concurrency and availability.
🔢
Enumerations
enum OrderState
PLACED | CONFIRMED | PACKED | SHIPPED | DELIVERED | CANCELLED
Enum prevents typo bugs in state names and enables exhaustive switch-case for state transitions, ensuring compile-time safety.
enum PaymentStatus
PENDING | SUCCESS | FAILED
Encapsulates payment outcomes explicitly, avoiding string literals and enabling clear state-dependent logic.
📦
Order
6 fields
private final String orderIdprivate volatile OrderState currentStateprivate PaymentStatus paymentStatusprivate final Customer customerprivate final List<OrderItem> itemsprivate final Object stateLock = new Object()
Represents a customer order, manages its state transitions atomically, and holds order details and payment status.
public String getOrderId()Returns the unique identifier of the order.
public OrderState getCurrentState()Returns the current state of the order.
public synchronized boolean transitionState(OrderState newState)Atomically attempts to transition the order to a new state if valid, returns true if successful.
public synchronized void updatePaymentStatus(PaymentStatus status)Updates the payment status of the order.
public List<OrderItem> getItems()Returns the list of items in the order.
📦
OrderItem
3 fields
private final String productIdprivate final int quantityprivate final double price
Represents a single item in an order with product details and pricing.
public String getProductId()Returns the product identifier.
public int getQuantity()Returns the quantity ordered.
public double getPrice()Returns the price per unit.
📦
Customer
3 fields
private final String customerIdprivate final String nameprivate final String email
Represents a customer placing orders.
public String getCustomerId()Returns the unique customer identifier.
public String getName()Returns the customer's name.
public String getEmail()Returns the customer's email.
📦
OrderStateHandler
1 fields
protected Order order
Abstract class defining behavior for order states and enforcing valid transitions.
public abstract boolean canTransitionTo(OrderState newState)Checks if transition to newState is valid from current state.
public void handleStateEntry()Hook method called when entering this state, can be overridden.
📦
PlacedStateHandler
0 fields
Concrete state handler for PLACED state, defines allowed transitions.
public boolean canTransitionTo(OrderState newState)Allows transition to CONFIRMED or CANCELLED only.
📦
ConfirmedStateHandler
0 fields
Concrete state handler for CONFIRMED state, defines allowed transitions.
public boolean canTransitionTo(OrderState newState)Allows transition to PACKED or CANCELLED only.
📦
PackedStateHandler
0 fields
Concrete state handler for PACKED state, defines allowed transitions.
public boolean canTransitionTo(OrderState newState)Allows transition to SHIPPED only.
📦
ShippedStateHandler
0 fields
Concrete state handler for SHIPPED state, defines allowed transitions.
public boolean canTransitionTo(OrderState newState)Allows transition to DELIVERED only.
📦
DeliveredStateHandler
0 fields
Concrete state handler for DELIVERED state, no further transitions allowed.
public boolean canTransitionTo(OrderState newState)No transitions allowed from DELIVERED.
📦
CancelledStateHandler
0 fields
Concrete state handler for CANCELLED state, terminal state.
public boolean canTransitionTo(OrderState newState)No transitions allowed from CANCELLED.
🔗
Relationships
Order◆──►OrderItem[1..*]
compositionOrder owns OrderItems; deleting Order deletes items.
Order──►Customer[1]
associationOrder references Customer; Customer exists independently.
OrderStateHandler──►Order[1]
associationStateHandler operates on a single Order instance.
🗄️
Orders
PK: orderId
orderId STRINGcustomerId STRINGcurrentState STRINGpaymentStatus STRINGorderDate TIMESTAMP
Stores order metadata and current state.
🗄️
OrderItems
PK: orderId
orderId STRINGproductId STRINGquantity INTprice DOUBLE
Stores items belonging to each order.
🔌
PlaceOrder
Request
{
  "customerId": "STRING",
  "items": "List<OrderItem>"
}
Response
{
  "orderId": "STRING",
  "status": "PLACED"
}
Creates a new order in PLACED state.
🔌
GetOrderStatus
Request
{
  "orderId": "STRING"
}
Response
{
  "orderId": "STRING",
  "currentState": "OrderState",
  "paymentStatus": "PaymentStatus"
}
Returns current state and payment status of the order.
🔌
CancelOrder
Request
{
  "orderId": "STRING"
}
Response
{
  "success": "BOOLEAN",
  "message": "STRING"
}
Attempts to cancel order if allowed by current state.

Practice

(1/5)
1. In a notification system, a NotificationFactory class has a static method that returns different Notification subclasses (e.g., EmailNotification, SMSNotification) based on input parameters. Which design pattern is applied here and why is it the correct choice?
easy
A. Builder pattern, because it constructs complex notification objects step-by-step.
B. Factory pattern, because it encapsulates object creation and returns subclasses based on input.
C. Singleton pattern, because it ensures only one factory instance exists.
D. Decorator pattern, because it adds responsibilities to notifications dynamically.

Solution

  1. Step 1: Identify the role of NotificationFactory

    The factory method returns different Notification subclasses based on input parameters, encapsulating object creation logic.
  2. Step 2: Eliminate other patterns

    Builder is for stepwise construction, Singleton ensures single instance, Decorator adds behavior dynamically; none match the described creation logic.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Factory pattern encapsulates subclass instantiation based on input [check]
Hint: Factory creates objects based on input type [check]
Common Mistakes:
2. In the Elevator System, should the Elevator class implement an interface or extend an abstract class to represent different elevator types (e.g., passenger, freight)? Consider that elevators share common state and behavior but also have type-specific logic.
easy
A. Use an abstract class, because elevators share common state and partial behavior implementations.
B. Use an interface, because elevators only share behavior signatures, not state.
C. Use a concrete class, because inheritance is unnecessary for elevator types.
D. Use multiple interfaces, one per behavior, to avoid state duplication.

Solution

  1. Step 1: Analyze shared state and behavior

    Elevators share common fields like currentFloor, direction, and doorStatus, plus some implemented methods.
  2. Step 2: Abstract class fits shared state and partial behavior

    Abstract class allows code reuse and enforces common state, while subclasses override type-specific logic.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Abstract class supports shared state and behavior [check]
Hint: Abstract class for shared state; interface for pure behavior [check]
Common Mistakes:
3. The Wallet System currently calculates fees with a FeeStrategy interface. To add a WeekendFeeStrategy without modifying existing classes, which SOLID principle is being applied and what is the minimum required change?
medium
A. Open/Closed Principle: create WeekendFeeStrategy implementing FeeStrategy; no existing class changes.
B. Dependency Inversion Principle: inject WeekendFeeStrategy into Account class by modifying Account.
C. Single Responsibility Principle: modify FeeStrategy to handle weekends explicitly.
D. Liskov Substitution Principle: override FeeStrategy methods in WeekendFeeStrategy and modify Transaction.

Solution

  1. Step 1: Identify the SOLID principle for extensibility

    Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: Apply OCP to fee calculation

    Adding WeekendFeeStrategy as a new class implementing FeeStrategy extends behavior without modifying existing classes, preserving OCP.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New FeeStrategy implementation -> no existing class changes -> OCP [check]
Hint: Add new strategy class, no existing code change -> OCP [check]
Common Mistakes:
4. Adding a WeekendFeeStrategy to the current parking fee system requires which minimum change to comply with SOLID principles?
medium
A. Add a boolean flag isWeekend in ParkingLot and conditionally apply fees inside existing strategies.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy without modifying existing classes.
C. Modify the existing FeeStrategy interface to add a isWeekend() method and update all implementations.
D. Combine all fee strategies into one class with conditional logic for weekends.

Solution

  1. Step 1: Identify applicable SOLID principle

    The Open/Closed Principle (OCP) requires that classes be open for extension but closed for modification.
  2. Step 2: Evaluate options against OCP

    Create a new WeekendFeeStrategy class implementing FeeStrategy without modifying existing classes. respects OCP by adding a new class without modifying existing ones. Add a boolean flag isWeekend in ParkingLot and conditionally apply fees inside existing strategies. violates OCP by modifying ParkingLot and existing strategies with conditional logic.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class added, existing code unchanged -> OCP respected [check]
Hint: Add new strategy class, don't modify existing ones [check]
Common Mistakes:
5. ElectricCar requires ChargingSpots in the parking lot system. What is the minimum change to support this without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType, CHARGING to SpotType, create ElectricCar extending Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
B. Modify Vehicle class to include a chargingRequired flag and update all spot checks.
C. Create a new ChargingSpot class and modify ParkingLot to handle it specially.
D. Add a new interface Chargeable and make ElectricCar implement it, changing existing spot logic.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and a subclass extends functionality without changing existing class code, respecting OCP.
  2. Step 2: Evaluate options

    Modify Vehicle class to include a chargingRequired flag and update all spot checks. modifies Vehicle, violating OCP. Create a new ChargingSpot class and modify ParkingLot to handle it specially. requires modifying ParkingLot, violating minimal change. Add a new interface Chargeable and make ElectricCar implement it, changing existing spot logic. adds interface but requires changing spot logic, violating minimal change.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + subclass + compatibility map update -> minimal change [check]
Hint: Add enums + subclass + compatibility map, no existing class change [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard