Design a Coffee Machine
What is the Coffee Machine Problem?
Section titled “What is the Coffee Machine Problem?”Design a coffee machine system that can prepare various beverages (coffee, tea, cappuccino, latte) based on predefined recipes, manage ingredient inventory (coffee beans, milk, water, sugar), allow user customization (sugar level, milk type), monitor ingredient levels with alerts, and handle the dispensing process with proper state management.
In this problem, you’ll design a system that handles multiple beverage types, user customizations, and ensures the machine remains in a valid state throughout the brewing process.
Problem Overview
Section titled “Problem Overview”Design a coffee machine that prepares various drinks based on recipes, tracks ingredient levels, and provides a seamless user experience through state-aware operations.
Core Requirements
Section titled “Core Requirements”Functional Requirements:
- Beverage Variety: Support multiple types (Coffee, Tea, Cappuccino, Latte) using the Factory Pattern.
- Inventory Management: Track ingredients (beans, milk, water, sugar) with real-time quantity tracking.
- Recipe System: Each beverage has a predefined recipe; validate availability before starting.
- Customization: Allow users to select sugar level (None to High) and milk type (Regular, Skim, Almond).
- Alert System: Monitor ingredient levels and notify when they fall below a threshold (e.g., 20%).
- State Management: Manage operational states (Idle, Preparing, Dispensing, Maintenance).
- Preparation Flow: Handle the full lifecycle: validate → consume → prepare → dispense → Idle.
- Error Handling: Gracefully reject requests if validation fails or ingredients run out mid-brew.
- Maintenance: Support refilling ingredients to restore inventory levels.
Non-Functional Requirements:
- Thread Safety: Ensure inventory operations are thread-safe for concurrent preparation requests.
- Modular Design: Each class should have well-defined roles following the Single Responsibility Principle.
- Extensibility: Easy to add new beverages, ingredients, or customizations without refactoring.
- Reliability: The core preparation logic and state management must be easy to test and maintain.
What’s Expected?
Section titled “What’s Expected?”1. System Architecture
Section titled “1. System Architecture”The system coordinates between the User Interface, the Inventory Manager, and the Brewing Engine.
2. Key Classes to Design
Section titled “2. Key Classes to Design”classDiagram
class CoffeeMachine {
-MachineState currentState
-Inventory inventory
+selectBeverage(type)
+dispense()
}
class Inventory {
-Map~Ingredient, Quantity~ stock
+hasEnough(recipe)
+consume(recipe)
}
class Beverage {
<<abstract>>
-Recipe recipe
+prepare()*
}
class Coffee {
+prepare()
}
class MachineState {
<<interface>>
+handleAction()
}
CoffeeMachine --> MachineState
CoffeeMachine --> Inventory
Beverage <|-- Coffee
Beverage --> Recipe
System Flow
Section titled “System Flow”Beverage Preparation Flow
Section titled “Beverage Preparation Flow”Key Design Challenges
Section titled “Key Design Challenges”1. Machine State Transitions
Section titled “1. Machine State Transitions”A coffee machine shouldn’t allow a user to select a drink while it’s already brewing or when it’s in a maintenance/error state.
Solution: Use the State Pattern. Define states like IdleState, BrewingState, DispensingState, and OutOfOrderState. Each state object defines what actions are allowed, preventing invalid transitions.
2. Ingredient Monitoring
Section titled “2. Ingredient Monitoring”The system needs to alert someone when beans or milk are low, but the Inventory shouldn’t be tightly coupled to a notification system.
Solution: Use the Observer Pattern. The Inventory acts as a Subject, and various AlertSystems (Email, Console, LED) act as Observers that get notified when levels cross a threshold.
3. Concurrency in Inventory
Section titled “3. Concurrency in Inventory”If two requests come in simultaneously, they might both see enough milk available but together exceed the stock.
Solution: Implement Thread-Safe Inventory. Use locks or atomic operations (like ConcurrentHashMap and AtomicInteger) to ensure that checking and consuming ingredients is an atomic operation.
What You’ll Learn
Section titled “What You’ll Learn”By solving this problem, you’ll master:
- ✅ State Management - Controlling complex object lifecycles.
- ✅ Inventory Logic - Managing resource allocation and tracking.
- ✅ Decoupling - Using Observers to separate logic from notifications.
- ✅ Factory Method - Dynamically creating objects based on configuration.
View Complete Solution & Practice
Section titled “View Complete Solution & Practice”Ready to see the full implementation? Open the interactive playground to access:
- 🎯 Step-by-step guidance through the 8-step LLD approach
- 📊 Interactive UML builder to visualize your design
- 💻 Complete Code Solutions in Python, Java, C++, TypeScript, JavaScript, C#
- 🤖 AI-powered review of your design and code
Related Problems
Section titled “Related Problems”After mastering Coffee Machine, try these similar problems:
- Vending Machine - Similar state and inventory logic.
- ATM System - Complex state transitions and security.
- Parking Lot - Resource management and allocation.