Home/Learn/Java A–Z/Factory Pattern

Factory Pattern

Intermediate
Design Patterns

Factory patterns decouple object creation from usage, enabling flexible instantiation without tight coupling to concrete types.

Overview

Factory patterns encapsulate the creation logic for objects. There are three related patterns: Static Factory Method (replaces constructors), Factory Method (subclasses decide which class to instantiate), and Abstract Factory (creates families of related objects). All three promote the Open/Closed Principle — new types can be added without changing existing client code.

Static Factory Methods

A static factory method is a named static method that returns an instance. Unlike constructors, factory methods: have meaningful names, can return cached/pooled instances, can return subtypes, and can avoid creating an object when possible.

Java standard library examples: Integer.valueOf(), Optional.of(), List.of(), Path.of().

StaticFactory.java
public class Currency {
    private final String code;
    private static final Map<String, Currency> CACHE = new HashMap<>();

    private Currency(String code) { this.code = code; }

    // Static factory methods — named, can cache
    public static Currency of(String code) {
        return CACHE.computeIfAbsent(
            code.toUpperCase(), Currency::new);
    }

    public static Currency usd() { return of("USD"); }
    public static Currency eur() { return of("EUR"); }

    // vs constructors — can return subtype
    public static Number parse(String s) {
        if (s.contains(".")) return Double.parseDouble(s);
        return Long.parseLong(s);
    }
}

// Client — no coupling to Currency constructor
Currency usd  = Currency.of("USD");
Currency usd2 = Currency.of("USD");
assert usd == usd2; // same cached instance

Factory Method Pattern

The Factory Method pattern defines an interface for creating an object but lets subclasses decide which class to instantiate. The creator class calls the factory method; concrete creators override it.

This is the most common factory pattern in framework design — e.g., Spring's FactoryBean, JDBC's Connection creation.

FactoryMethod.java
// Abstract creator
public abstract class NotificationSender {
    // Factory method — subclasses override
    protected abstract Notification createNotification(String message);

    // Template method that uses the factory method
    public void send(String message) {
        Notification n = createNotification(message);
        n.deliver();
        n.logDelivery();
    }
}

// Concrete creators
public class EmailSender extends NotificationSender {
    @Override
    protected Notification createNotification(String message) {
        return new EmailNotification(message, this.smtpConfig);
    }
}

public class SmsSender extends NotificationSender {
    @Override
    protected Notification createNotification(String message) {
        return new SmsNotification(message, this.twilioConfig);
    }
}

// Client — works with any sender
NotificationSender sender = new EmailSender();
sender.send("Your order has shipped!");

Abstract Factory Pattern

Abstract Factory creates families of related objects without specifying their concrete classes. If you need multiple related objects that must be consistent (e.g., UI components for different themes or platforms), Abstract Factory ensures consistency.

The client depends only on the abstract factory interface, not on concrete implementations.

AbstractFactory.java
// Abstract factory interface
public interface UIFactory {
    Button  createButton();
    TextBox createTextBox();
    Dialog  createDialog();
}

// Concrete factories
public class DarkThemeFactory implements UIFactory {
    @Override public Button  createButton()  { return new DarkButton();  }
    @Override public TextBox createTextBox() { return new DarkTextBox(); }
    @Override public Dialog  createDialog()  { return new DarkDialog();  }
}

public class LightThemeFactory implements UIFactory {
    @Override public Button  createButton()  { return new LightButton();  }
    @Override public TextBox createTextBox() { return new LightTextBox(); }
    @Override public Dialog  createDialog()  { return new LightDialog();  }
}

// Client — completely decoupled from concrete types
public class Application {
    private final UIFactory factory;

    public Application(UIFactory factory) { this.factory = factory; }

    public void render() {
        Button btn = factory.createButton();
        TextBox tb  = factory.createTextBox();
        btn.render(); tb.render();
    }
}

Key Points to Remember

  • Static factory methods have names, can cache, and can return subtypes — prefer over constructors for complex creation.
  • Factory Method delegates instantiation to subclasses — open/closed principle in action.
  • Abstract Factory creates consistent families of related objects without coupling to concrete classes.
  • Java standard library uses static factories extensively: List.of(), Optional.of(), Path.of().
  • Factory patterns improve testability — inject a mock factory to control what is created.

Practice Factory Pattern in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

What is the difference between Factory Method and Abstract Factory patterns?

MediumAmazon
2

Why does Effective Java recommend static factory methods over constructors?

MediumGoogle
3

How does List.of() differ from new ArrayList<>()?

EasyOracle
4

Give a real-world example of the Abstract Factory pattern in Java frameworks.

MediumMicrosoft
5

How do factory patterns support the Open/Closed Principle?

MediumNetflix

Ask Aria about Factory Pattern

Your personal AI tutor — ask anything about this concept