Real-World Case Study: E-Commerce Order Processing System
4 min read
Lesson slides
1 / 15
Problem Statement
You're designing an e-commerce system that needs to:
- Handle different types of products (physical, digital, subscription)
- Support multiple payment methods
- Send notifications to various channels
- Process orders with complex business rules
- Support order modifications and cancellations
System Architecture Overview
graph TB
subgraph "Client Layer"
UI[Web UI]
API[REST API]
end
subgraph "Facade Layer"
OMF[OrderManagementFacade]
end
subgraph "Business Logic"
OB[OrderBuilder]
PF[ProductFactory]
PS[PaymentStrategy]
OP[OrderProcessor]
end
subgraph "Services"
IS[InventoryService]
PS2[PaymentService]
SS[ShippingService]
NS[NotificationService]
end
subgraph "Command System"
CI[CommandInvoker]
POC[PlaceOrderCommand]
COC[CancelOrderCommand]
end
UI --> OMF
API --> OMF
OMF --> OB
OMF --> PF
OMF --> PS
OMF --> OP
OMF --> IS
OMF --> PS2
OMF --> SS
OMF --> NS
OMF --> CI
CI --> POC
CI --> COCPattern Integration Flow
sequenceDiagram
participant Client
participant Facade as OrderManagementFacade
participant Builder as OrderBuilder
participant Factory as ProductFactory
participant Strategy as PaymentStrategy
participant Observer as NotificationSystem
participant Command as CommandInvoker
Client->>Facade: placeOrder(orderData)
Facade->>Builder: createOrder()
Builder->>Factory: createProduct(type, data)
Factory-->>Builder: Product
Builder-->>Facade: Order
Facade->>Strategy: processPayment(order)
Strategy-->>Facade: PaymentResult
Facade->>Observer: notifyStatusChange("paid")
Observer-->>Facade: notifications sent
Facade->>Command: execute(PlaceOrderCommand)
Command-->>Facade: order placed
Facade-->>Client: OrderConfirmationAnalysis and Pattern Selection
Creational Patterns Needed:
- Factory Pattern for Product Creation:
class ProductFactory:
@staticmethod
def create_product(product_type, **kwargs):
if product_type == "physical":
return PhysicalProduct(**kwargs)
elif product_type == "digital":
return DigitalProduct(**kwargs)
elif product_type == "subscription":
return SubscriptionProduct(**kwargs)- Builder Pattern for Order Creation:
class OrderBuilder:
def __init__(self):
self.order = Order()
def add_product(self, product):
self.order.products.append(product)
return self
def set_customer(self, customer):
self.order.customer = customer
return self
def set_shipping_address(self, address):
self.order.shipping_address = address
return self
def apply_discount(self, discount):
self.order.discount = discount
return selfStructural Patterns Needed:
- Decorator Pattern for Order Processing:
class OrderProcessorDecorator:
def __init__(self, processor):
self.processor = processor
def process(self, order):
return self.processor.process(order)
class TaxCalculatorDecorator(OrderProcessorDecorator):
def process(self, order):
result = self.processor.process(order)
# Add tax calculation logic
return result
class ShippingCalculatorDecorator(OrderProcessorDecorator):
def process(self, order):
result = self.processor.process(order)
# Add shipping calculation logic
return result- Facade Pattern for Order Management:
class OrderManagementFacade:
def __init__(self):
self.inventory = InventoryService()
self.payment = PaymentService()
self.shipping = ShippingService()
self.notification = NotificationService()
def place_order(self, order):
# Orchestrate all services
self.inventory.reserve_items(order.products)
payment_result = self.payment.process_payment(order)
if payment_result.success:
self.shipping.schedule_delivery(order)
self.notification.send_confirmation(order)
return payment_resultBehavioral Patterns Needed:
- Strategy Pattern for Payment Processing:
class PaymentProcessor:
def __init__(self):
self.strategy = None
def set_payment_strategy(self, strategy):
self.strategy = strategy
def process_payment(self, order):
return self.strategy.pay(order.total_amount)- Observer Pattern for Order Status Updates:
class Order(Subject):
def __init__(self):
super().__init__()
self._status = "pending"
@property
def status(self):
return self._status
@status.setter
def status(self, new_status):
self._status = new_status
self.notify(f"Order status changed to {new_status}")- Command Pattern for Order Operations:
class PlaceOrderCommand(Command):
def __init__(self, order_service, order):
self.order_service = order_service
self.order = order
def execute(self):
return self.order_service.place_order(self.order)
def undo(self):
return self.order_service.cancel_order(self.order)Pattern Selection Decision Matrix
graph TD
A[Design Decision] --> B{Object Creation Complexity?}
B -->|Simple| C[Direct Constructor]
B -->|Multiple Types| D[Factory Pattern]
B -->|Many Parameters| E[Builder Pattern]
B -->|Single Instance| F[Singleton Pattern]
A --> G{Interface Compatibility?}
G -->|Incompatible| H[Adapter Pattern]
G -->|Add Behavior| I[Decorator Pattern]
G -->|Simplify Complex| J[Facade Pattern]
A --> K{Communication Pattern?}
K -->|One-to-Many Updates| L[Observer Pattern]
K -->|Multiple Algorithms| M[Strategy Pattern]
K -->|Queue/Undo Operations| N[Command Pattern]Complete Integration Example:
# Using multiple patterns together
def process_ecommerce_order():
# Builder pattern for order creation
order = (OrderBuilder()
.set_customer(customer)
.add_product(ProductFactory.create_product("physical", name="Laptop"))
.add_product(ProductFactory.create_product("digital", name="Software"))
.set_shipping_address(address)
.build())
# Strategy pattern for payment
payment_processor = PaymentProcessor()
payment_processor.set_payment_strategy(CreditCardPayment("1234567890"))
# Observer pattern for notifications
order.attach(EmailNotification())
order.attach(SMSNotification())
# Decorator pattern for processing
processor = BasicOrderProcessor()
processor = TaxCalculatorDecorator(processor)
processor = ShippingCalculatorDecorator(processor)
# Command pattern for execution
command = PlaceOrderCommand(order_service, order)
result = command.execute()
# Facade pattern for coordination
facade = OrderManagementFacade()
return facade.place_order(order)Pattern Selection Reasoning Matrix:
| Pattern | Problem Solved | Why Chosen | Alternative Considered |
|---|---|---|---|
| Factory | Different product types | Runtime type determination | Direct instantiation (too rigid) |
| Builder | Complex order creation | Many optional parameters | Constructor overloading (unwieldy) |
| Strategy | Payment methods | Runtime algorithm switching | If-else chains (hard to extend) |
| Observer | Notifications | Decoupled communication | Direct method calls (tight coupling) |
| Decorator | Order processing | Flexible responsibility chain | Inheritance (explosion of classes) |
| Command | Order operations | Undo/redo + queuing | Direct method calls (no undo) |
| Facade | System complexity | Simplified interface | Direct service calls (complex client) |