SDE Path

Design Patterns

Creational Patterns That Earn Their Keep

Factory, Builder, Singleton, Prototype — when object creation deserves its own abstraction, and when it doesn't.

12 min5 steps · 7 checks
Step 1 of 50/7 checks correct

Scattering new ConcreteThing() across a codebase glues every caller to a specific class. The day you add a variant, you grep for every construction site and edit each one. Factory Method centralizes that decision behind a single seam so callers ask for a capability and stay ignorant of which concrete class satisfies it.

Start with the smell: construction logic tangled into the code that uses the object.

// Scattered construction — every caller decides the concrete type.
Shape s;
if (kind.equals("circle"))      s = new Circle(radius);
else if (kind.equals("square")) s = new Square(side);
else                            throw new IllegalArgumentException(kind);
s.draw();

That if ladder is copy-pasted wherever a shape is built. Pull the choice into one factory and callers depend only on the Shape interface:

interface Shape { void draw(); }

class ShapeFactory {
    Shape create(String kind) {
        return switch (kind) {
            case "circle" -> new Circle();
            case "square" -> new Square();
            default -> throw new IllegalArgumentException("unknown: " + kind);
        };
    }
}

// Caller: no 'new', no knowledge of concrete classes.
Shape s = factory.create(kind);
s.draw();

The payoff arrives on day two. Adding a Triangle touches exactly one place — the factory — instead of every construction site. It also gives you a natural home for construction concerns like pooling, caching, or reading the type from config. The cost is one extra indirection, so reach for it when the set of concrete types is genuinely open or the choice logic is duplicated; skip it when you build one fixed type in one place.

Quick check

What is the primary benefit of routing object creation through a ShapeFactory instead of scattering new Circle() / new Square() at call sites?