Design pattern to be used in Pizza Shop LLD
Let's disect it
Here’s a low-level design (LLD) for a Pizza Shop system in Java. This design includes key entities like Pizza, Order, Customer, Payment, and Toppings, while ensuring modularity and flexibility using OOP principles such as inheritance and composition.
Key Components:
Pizza (Base Class & Variants)
Toppings (Decorator Pattern)
Order Management
Payment Handling
Customer & Store Management
1. Factory Pattern (For Creating Pizzas Dynamically)
Instead of manually instantiating pizzas, we use a Factory Pattern.
Pizza Factory Code
class PizzaFactory {
public static Pizza createPizza(String type) {
switch (type.toLowerCase()) {
case "margherita":
return new Margherita();
case "pepperoni":
return new Pepperoni();
default:
throw new IllegalArgumentException("Unknown Pizza Type: " + type);
}
}
}
Usage
Pizza pizza = PizzaFactory.createPizza("margherita");
2. Decorator Pattern (For Adding Toppings)
This pattern allows us to dynamically extend the Pizza functionality.
Decorator Pattern Code
This was implemented in the original design:
abstract class ToppingDecorator extends Pizza {
protected Pizza pizza;
public ToppingDecorator(Pizza pizza) {
this.pizza = pizza;
}
public abstract String getDescription();
}
class Cheese extends ToppingDecorator {
public Cheese(Pizza pizza) {
super(pizza);
}
public String getDescription() {
return pizza.getDescription() + ", Cheese";
}
public double getCost() {
return pizza.getCost() + 1.50;
}
}
Usage
Pizza pizza = new Cheese(new Pepperoni()); // Pepperoni with extra cheese
3. Singleton Pattern (For Order Management)
We ensure a single instance of OrderManager to manage all orders.
Singleton OrderManager
public class OrderManager {
private static volatile OrderManager instance;
private List<Order> orders;
private OrderManager() {
orders = new ArrayList<>();
}
public static OrderManager getInstance() {
if (instance == null) { // First check (without locking)
synchronized (OrderManager.class) {
if (instance == null) { // Second check (inside lock)
instance = new OrderManager();
}
}
}
return instance;
}
public void addOrder(Order order) {
orders.add(order);
System.out.println("Order added: " + order);
}
public List<Order> getOrders() {
return orders;
}
}
4. Strategy Pattern (For Payment Methods)
This pattern allows flexible payment method handling.
Payment Strategy Code
interface PaymentStrategy {
boolean pay(double amount);
}
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}
public boolean pay(double amount) {
System.out.println("Paid $" + amount + " via Credit Card: " + cardNumber);
return true;
}
}
class CashPayment implements PaymentStrategy {
public boolean pay(double amount) {
System.out.println("Paid $" + amount + " in Cash");
return true;
}
}
class PaymentProcessor {
private PaymentStrategy paymentStrategy;
public PaymentProcessor(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void processPayment(double amount) {
paymentStrategy.pay(amount);
}
}
Usage
PaymentProcessor paymentProcessor = new PaymentProcessor(new CreditCardPayment("1234-5678-9876-5432"));
paymentProcessor.processPayment(20.0);
5. Observer Pattern (For Order Status Notifications)
Used to notify customers when their order status changes.
Observer Pattern Code
import java.util.*;
interface Observer {
void update(String message);
}
class Customer implements Observer {
private String name;
public Customer(String name) {
this.name = name;
}
public void update(String message) {
System.out.println("Notification for " + name + ": " + message);
}
}
class OrderStatusNotifier {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
Usage
import java.util.*;
interface Observer {
void update(String message);
}
class Customer implements Observer {
private String name;
public Customer(String name) {
this.name = name;
}
public void update(String message) {
System.out.println("Notification for " + name + ": " + message);
}
}
class OrderStatusNotifier {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}

