Factory Patterns
Core Philosophy
Factory patterns encapsulate the logic of object creation. The client doesn't need to know the specific class being instantiated; it only interacts with an interface.
The Restaurant Metaphor: You order a dish from a menu (the interface). You don't care who the specific chef is or how they were hired; you just want the dish delivered to your table.
The Three Flavors of Factory
1. Simple Factory (Not a GoF Pattern)
A utility class with a static method that returns an instance based on input parameters.
public class PizzaFactory {
public static Pizza createPizza(String type) {
if (type.equals("Cheese")) return new CheesePizza();
if (type.equals("Veggie")) return new VeggiePizza();
throw new IllegalArgumentException();
}
}
- Flaw: Violates OCP (Open/Closed Principle). Every time you add a new pizza, you must modify the
PizzaFactoryclass.
2. Factory Method
Defining an interface for creating an object, but letting subclasses decide which class to instantiate.
public interface PizzaStore {
Pizza createPizza(); // The Factory Method
}
public class NYPizzaStore implements PizzaStore {
public Pizza createPizza() { return new NYStyleCheesePizza(); }
}
public class ChicagoPizzaStore implements PizzaStore {
public Pizza createPizza() { return new ChicagoStyleCheesePizza(); }
}
- Benefit: Fully compliant with OCP. To add a store, you create a new class without touching existing ones.
3. Abstract Factory
An interface for creating families of related or dependent objects without specifying their concrete classes.
public interface IngredientFactory {
Dough createDough();
Sauce createSauce();
}
public class NYIngredientFactory implements IngredientFactory {
public Dough createDough() { return new ThinCrustDough(); }
public Sauce createSauce() { return new MarinaraSauce(); }
}
Comparison Matrix
| Pattern | Number of Factories | Scope | OCP Compliance | Best Use Case |
|---|---|---|---|---|
| Simple | 1 | Flat | ❌ No | Few, stable types |
| Method | 1 per Product | One Dimension | ✅ Yes | Extensible product lines |
| Abstract | 1 per Product Family | Multiple Dimensions | ✅ Yes | Product "Suites" (e.g., Cross-platform UI) |
Deep Technical Insights
Dependency Inversion in Factories
Factories enforce the Dependency Inversion Principle. Standard code depends on concrete classes (new Dog()). Factory code depends on abstractions (factory.createAnimal()). This decouples the high-level business logic from the low-level implementation details, making the system much easier to test and extend.
When to Avoid Factories
Don't use factories if your classes are simple and unlikely to change. Introducing a factory for every new in your codebase leads to "Interface Bloat" and unnecessary complexity. Only use them when you need to switch implementations at runtime or hide complex initialization logic.