Factory Pattern
IntermediateFactory 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().
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 instanceFactory 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.
// 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.
// 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 AriaWhat is the difference between Factory Method and Abstract Factory patterns?
Why does Effective Java recommend static factory methods over constructors?
How does List.of() differ from new ArrayList<>()?
Give a real-world example of the Abstract Factory pattern in Java frameworks.
How do factory patterns support the Open/Closed Principle?
Ask Aria about Factory Pattern
Your personal AI tutor — ask anything about this concept