Factory Pattern
1. What the factory pattern is
A factory is anything that hands you back an instance of some type without you having to invoke a constructor directly. The caller asks for what it wants; the factory decides how to build it and which concrete class to return.
That’s the whole idea, but “factory pattern” is a slightly overloaded term in Java. In practice, it covers two distinct things, and conversations about factories get tangled when people mean different ones:
- The static factory method: a static method on the class itself that returns an instance, in place of (or alongside) a public constructor.
List.of(...),Optional.of(...), andInteger.valueOf(...)are all examples from the standard library. Joshua Bloch’s Effective Java opens with this as Item 1. - The factory method pattern: the one the Gang of Four named. An abstract creator class declares a factory method; concrete subclasses override it to decide which concrete product gets returned. This is the polymorphic version, and it’s a heavier hammer.
Both solve the same underlying problem (don’t tie the caller to a concrete constructor) but they do it at different scales. Why that problem is worth solving in the first place is the question §2 takes up.
2. Why not just call new?
Truth is, most of the time calling new Foo() IS the right thing to do. Constructors are simple, and adding a factory layer to a class that only has one construction path is just noise. The pattern earns its keep when the constructor can’t express what you actually want, and Java’s constructor has more limitations than people usually notice.
Consider what a constructor cannot do:
- It cannot have a meaningful name. The constructor is named after the class. If you have two ways to build a
Point, Cartesian and polar, both arePoint(double, double), distinguishable only by parameter types. With factories you writePoint.fromCartesian(x, y)andPoint.fromPolar(r, θ), and the call site reads itself. - It cannot return a subtype.
new ArrayList<>()always returns exactly anArrayList. You cannot, from a constructor, decide at runtime to hand back aLinkedListinstead.List.of(1, 2, 3), on the other hand, can return whatever immutable list implementation is most efficient for that input. - It cannot return null, or fail gracefully. A constructor either runs to completion or throws. There’s no “I tried, here’s nothing” path. A factory can return
Optional.empty(),null, or a sentinel object when construction is invalid but not exceptional.
None of these on their own are necessarily dramatic, but together they show why factories show up across the standard library and most non-trivial codebases: the moment construction has any logic to it (a choice between subtypes, a validation that returns nothing instead of throwing, or just a more readable name, etc.) new runs out of room.
3. Writing one in Java
3.1. The static factory method
This is the lightweight version. Make the constructor private (or package-private), and expose one or more static methods that return instances. This way, the methods get to have descriptive names, and callers don’t have to worry about the actual constructor:
public final class Color {
private final int r, g, b;
private Color(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
public static Color fromRGB(int r, int g, int b) {
return new Color(r, g, b);
}
public static Color fromHex(String hex) {
// ...hex → RGB parsing
return new Color(/* ... */);
}
public static Color fromHSV(float h, float s, float v) {
// ...HSV → RGB conversion
return new Color(/* ... */);
}
}Color.fromRGB(255, 0, 0), Color.fromHex("#87ceeb"), and Color.fromHSV(0.6f, 0.5f, 1.0f) each say what they mean at the call site. A plain Color(0.6f, 0.5f, 1.0f) constructor wouldn’t: three floats could be HSV, HSL or normalized RGB, and the reader has to chase the definition to find out. Naming is the cheapest win the pattern offers, and most static factories exist for exactly that reason.
The other wins from §2 unlock once the constructor is hidden. This version of Color can later start returning a subtype, or returning null for invalid inputs, without changing a single call site. The factory absorbs the change.
3.2. The GoF factory method
The Gang of Four version is heavier. It’s a class hierarchy where the base class defines an algorithm that depends on creating some object, and subclasses decide which object to create.
The shape is easiest to see with a trimmed-down version of the canonical example from Head First Design Patterns: a PizzaStore base class that handles the order pipeline (prepare, bake, cut, box) but defers the “which pizza do we actually make” decision to regional subclasses:
public abstract class PizzaStore {
public final Pizza orderPizza() {
Pizza pizza = createPizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(); // <- factory method (must be overridden)
}
public class NYPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza() {
return new NYStylePizza();
}
}
public class ChicagoPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza() {
return new ChicagoStylePizza();
}
}createPizza() is the factory method. The base class never references NYStylePizza or ChicagoStylePizza directly; it only knows it needs a Pizza. Subclasses fill in the choice by overriding the factory method. New region? New PizzaStore subclass; the base stays untouched.
This is more machinery than a static factory method, and you should reach for it only when there really is a family of variants that share an algorithm but differ in what they construct. For a single class that just needs better-named constructors, §3.1 is the right tool.
A note on scope: when the family of products grows past one (when subclasses need to create matching sets of related objects rather than a single one); you’ve outgrown Factory Method and want Abstract Factory. Different pattern, covered separately.
4. When not to factory pattern
Factories are easy to over-apply, because the cost of adding one is so low, and it will feel like you’re doing something good. A few code smells to watch for:
- The factory wraps a single class that will never have a sibling. If an
EmailFactory.create(...)only ever returns anEmail, and there’s no realistic scenario where it’d return anything else, you’ve added an unnecessary layer. Just callnew Email(...). The factory is supposed to absorb a choice; if there’s no choice to absorb, it is just a longer way of writing the constructor. - The “factory” is a constructor in a hat. A static method called
Foo.create(x, y)whose entire body isreturn new Foo(x, y);is simply unnecessary; you might as well use the constructor. It looks like a factory, but provides none of the wins from §2. - The factory is really a builder. When the “factory” starts growing optional parameters, overloads with three different argument orders, or
withX(...)chained methods, you’ve reinvented the Builder pattern badly.
The honest rule of thumb: factories pay for themselves when construction has real logic, a choice, a name worth giving, an abstraction worth preserving. When all they do is forward to a constructor, they’re noise dressed up as architecture.