Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsMachine Coding Exercises
✓ FreeAdvanced· 6 min read

Multi-Pattern Problem: Design a Food Ordering Class Model

Combining State (order lifecycle) + Observer (customer/restaurant notification) — a smaller-scope companion to the Ride Booking multi-pattern exercise, with a direct focus on testability.

Published September 23, 2026


Multi-Pattern Problem: Design a Food Ordering Class Model

A deliberately smaller two-pattern combination (State + Observer, no Strategy this time) — worth doing specifically to practice the same justification discipline as the Ride Booking exercise, but without pricing/matching complexity distracting from the core two-pattern interaction.

Core classes

interface OrderState { OrderState advance(FoodOrder order); }
class PlacedState implements OrderState { public OrderState advance(FoodOrder order) { return new ConfirmedState(); } }
class ConfirmedState implements OrderState { public OrderState advance(FoodOrder order) { return new PreparingState(); } }
class PreparingState implements OrderState { public OrderState advance(FoodOrder order) { return new OutForDeliveryState(); } }
class OutForDeliveryState implements OrderState { public OrderState advance(FoodOrder order) { return new DeliveredState(); } }
class DeliveredState implements OrderState { public OrderState advance(FoodOrder order) { return this; } }

interface OrderObserver { void onStateChanged(FoodOrder order, OrderState newState); }
class CustomerNotificationObserver implements OrderObserver { public void onStateChanged(FoodOrder order, OrderState state) { /* push notification */ } }
class RestaurantDashboardObserver implements OrderObserver { public void onStateChanged(FoodOrder order, OrderState state) { /* update kitchen display */ } }

class FoodOrder {
    private OrderState state = new PlacedState();
    private final List<OrderObserver> observers = new CopyOnWriteArrayList<>();

    void advanceState() {
        state = state.advance(this);
        observers.forEach(o -> o.onStateChanged(this, state));
    }
}

This is a near-identical shape to Ride Booking's State+Observer half (and to Restaurant Management System's own order-state flow) — worth explicitly recognizing the repetition rather than re-deriving it as if novel, which is itself a strong signal: pattern recognition includes noticing "I've solved this exact combination before," not just recalling individual pattern definitions.

Testability: the specific angle this exercise asks for

@Test
void placedStateAdvancesTo Confirmed() {
    OrderState state = new PlacedState();
    OrderState next = state.advance(new FoodOrder()); // no mocking needed — advance() only depends on its own logic
    assertInstanceOf(ConfirmedState.class, next);
}

@Test
void advancingOrderNotifiesAllObservers() {
    FoodOrder order = new FoodOrder();
    OrderObserver mockObserver = mock(OrderObserver.class);
    order.addObserver(mockObserver);
    order.advanceState();
    verify(mockObserver).onStateChanged(eq(order), any(ConfirmedState.class));
}

Each OrderState implementation is testable in complete isolation — PlacedState.advance() needs nothing beyond a FoodOrder reference (which could be a bare, minimally-constructed instance, not a fully wired-up object graph) to verify it transitions correctly. Separately, FoodOrder.advanceState()'s notification behavior is testable with a mock OrderObserver, verifying the fact that observers get called on every transition without needing a real CustomerNotificationObserver (which would require mocking a push-notification service) at all. This isolation — testing state-transition logic and notification-firing behavior as two entirely separate concerns — is a direct, concrete payoff of State+Observer's decomposition, not just an abstract design-quality claim.

Follow-up questions this topic invites — and their answers

Q: What would testing look like WITHOUT this decomposition — say, if all logic lived in one FoodOrder.advance() method with a switch statement? A: Every test would need to construct a fully-wired FoodOrder AND stub/mock whatever notification mechanism was hard-coded inside that one method — testing 'does PLACED correctly transition to CONFIRMED' would be entangled with testing 'does a notification get sent,' making it impossible to verify one without the machinery for the other, exactly the coupling this design avoids.

Q: Why do CustomerNotificationObserver and RestaurantDashboardObserver both exist as separate classes rather than one CombinedObserver handling both concerns? A: Single Responsibility again — customer-facing push notifications and an internal kitchen dashboard update are genuinely different concerns with different failure modes and different owners; combining them would mean a kitchen-dashboard-update bug risking breaking customer notifications too, an unnecessary coupling this separation avoids.

Q: Is CopyOnWriteArrayList the right choice for FoodOrder's observers list here, same as elsewhere in this course? A: Yes, for the same reason as Design a Notification/Observer-Based Pub-Sub — observers are registered rarely (once, typically at order creation) and iterated frequently (on every state change), exactly CopyOnWriteArrayList's target profile.

Q: How would you extend this to support order cancellation, which doesn't fit the linear advance() progression? A: A cancellation likely needs to be modeled as a transition available from MULTIPLE states (Placed, Confirmed, Preparing can all potentially be cancelled; OutForDelivery/Delivered likely can't) — this would mean adding a separate cancel() method to the OrderState interface (not just advance()), with each state implementation deciding whether cancellation is even valid from that state, a natural extension of the same interface-per-state structure.

Previous

Multi-Pattern Problem: Design a Ride Booking Class Model

Next

Design an Authentication/Authorization Module

AI Tutor

Lesson: Multi-Pattern Problem: Design a Food Ordering Class Model

Quick actions

AI responses can be inaccurate. Verify critical information.