Low Level Design

Factory Pattern — Centralise Object Creation in Java

How the Factory Method pattern eliminates scattered `new` calls, enforces the Open/Closed Principle, and keeps object creation logic in one place.

August 26, 2026·9 min read

What is the Factory Pattern?#

The Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses (or a dedicated factory class) to decide which concrete type gets instantiated.

It encapsulates object creation logic in a separate method or class, letting the system create objects based on given parameters without the caller knowing the concrete type.

You reach for Factory when:

  • The exact type of object to create isn't known until runtime
  • Object creation logic is complex, repetitive, or needs to be centralised
  • You want to follow Open/Closed Principle — open for extension, closed for modification

Real-World Analogy#

Think of a notification desk in a company that sends messages to users. Initially the desk only sends emails. As new channels appear — SMS, Push, Slack, WhatsApp — the desk gets overwhelmed creating each type manually.

Instead of the desk handling creation, a Notification Factory produces the correct notification object for each channel. The desk just says "give me a Slack notifier" and uses it.


Class Diagram#


Violation Code — The Problem#

java
class NotificationService {
    public void sendNotification(String type, String message) {
        if (type.equals("EMAIL")) {
            EmailNotification email = new EmailNotification();
            email.send(message);
        } else if (type.equals("SMS")) {
            SMSNotification sms = new SMSNotification();
            sms.send(message);
        } else if (type.equals("PUSH")) {
            PushNotification push = new PushNotification();
            push.send(message);
        } else if (type.equals("SLACK")) {
            SlackNotification slack = new SlackNotification();
            slack.send(message);
        }
        // Adding WhatsApp means touching this method again ❌
    }
}

Issues:

  1. Tight coupling — caller depends on every concrete notification class
  2. Violates Open/Closed — adding a new channel forces modifying NotificationService
  3. Code duplication — creation logic is scattered and repeated
  4. Violates SRP — the service handles both business logic and object construction
  5. Hard to test — can't substitute mock objects easily

Enhanced Code — Factory Pattern#

java
// Product interface
public interface Notification {
    void send(String message);
}

// Concrete products
public class EmailNotification implements Notification {
    @Override
    public void send(String message) {
        System.out.println("Sending EMAIL: " + message);
    }
}

public class SMSNotification implements Notification {
    @Override
    public void send(String message) {
        System.out.println("Sending SMS: " + message);
    }
}

public class PushNotification implements Notification {
    @Override
    public void send(String message) {
        System.out.println("Sending PUSH: " + message);
    }
}

public class SlackNotification implements Notification {
    @Override
    public void send(String message) {
        System.out.println("Sending SLACK: " + message);
    }
}

// The Factory — centralises creation
public class NotificationFactory {
    public static Notification createNotification(String type) {
        switch (type.toUpperCase()) {
            case "EMAIL":   return new EmailNotification();
            case "SMS":     return new SMSNotification();
            case "PUSH":    return new PushNotification();
            case "SLACK":   return new SlackNotification();
            default: throw new IllegalArgumentException("Unknown type: " + type);
        }
    }
}

// Service — only knows about the interface, not concrete types
public class NotificationService {
    public void sendNotification(String type, String message) {
        Notification notification = NotificationFactory.createNotification(type);
        notification.send(message);
    }
}

Now adding WhatsAppNotification means:

  1. Create WhatsAppNotification implements Notification
  2. Add one case "WHATSAPP" to the factory

NotificationService is never touched.


Common LLD Problems Using Factory Pattern#

1. Notification Sender#

  • Factory: NotificationFactory.create("email" | "sms" | "push")
  • Context: Create the right handler without exposing instantiation logic.

2. Payment Gateway Integration#

  • Factory: PaymentFactory.getPayment("upi" | "credit_card" | "paypal")
  • Products: UPIPayment, CreditCardPayment, PayPalPayment
  • Context: Abstract away payment processor initialization.

3. Document / File Parser#

  • Factory: ParserFactory.getParser("pdf" | "docx" | "csv")
  • Products: PDFParser, DocxParser, CSVParser
  • Context: Read files of various formats without hardcoding parser logic.

4. Food Ordering System#

  • Factory: PizzaFactory.create("margherita" | "veggie" | "pepperoni")
  • Context: Decouple pizza creation from ordering logic.

5. Database Connection Provider#

  • Factory: ConnectionFactory.getConnection("mysql" | "postgres" | "mongodb")
  • Context: Unified access to different databases without changing business logic.

6. Shape Drawing Tool#

  • Factory: ShapeFactory.create("circle" | "rectangle" | "triangle")
  • Context: Create different shape objects in a diagramming or drawing tool.

7. Vehicle Manufacturing#

  • Factory: VehicleFactory.getVehicle("car" | "bike" | "truck")
  • Context: Manage object creation for different vehicle types uniformly.

8. Cloud Provider SDK#

  • Factory: CloudFactory.getProvider("aws" | "gcp" | "azure")
  • Products: AWSClient, GCPClient, AzureClient
  • Context: Simplify instantiation of cloud-specific clients.

Factory vs Abstract Factory#

FactoryAbstract Factory
CreatesOne product typeFamilies of related products
ScopeSingle objectMultiple related objects
Use whenYou need one kind of objectProducts must work together

ReferencesLinks
Article ReferenceRefactoring Guru — Factory Method