Week 2: The Factory Method Pattern Explained Simply
Design Patterns Demystified Series

In Week 1, we explored the Singleton Pattern — ensuring a single instance of a class exists globally.
This week, we’re diving into a slightly more sophisticated creational pattern:
The Factory Method Pattern, one of the official Gang of Four (GoF) design patterns.
Let’s break it down the simple way — with plain language, real-world analogies, and working code.
🤖 What is the Factory Method Pattern?
The Factory Method Pattern is a creational design pattern that:
Defines an interface for creating an object,
But let subclasses decide which class to instantiate.
Instead of hardcoding object creation (new), the pattern delegates the instantiation to a factory method, typically declared in a superclass and overridden in subclasses.
This promotes loose coupling and follows the Open/Closed Principle — your code is open for extension but closed for modification.
☕ Real-World Analogy: The Coffee Machine
Imagine an office cafe where employees can order coffee. But instead of preparing the drink themselves, they select a coffee flavor, and the machine takes care of everything.
Here's what happens:
Alice orders Espresso
Bob orders Cappuccino
Behind the scenes, the machine selects the correct recipe and serves the drink. Each type of coffee has a different preparation method, but the interface to the user remains the same.
In this analogy:
The coffee machine is the abstract class (with a factory method)
Each flavor is a concrete subclass that defines how to create its specific coffee
The user (client) only needs to request a flavor; they don’t know (or care) how it’s made
Both Alice and Bob interact with the same machine, using the same button interface, but get different results based on their input.
☕ Let's Translate That Into Code
Product Interface –
Coffee.javapublic interface Coffee { void brewCoffee(String user); }Concrete Products –
EspressoCoffee.javaandCappuccinoCoffee.javapublic class EspressoCoffee implements Coffee { @Override public void brewCoffee(String user) { System.out.println("Brewing Espresso coffee for " + user); } }public class CappuccinoCoffee implements Coffee { @Override public void brewCoffee(String user) { System.out.println("Brewing Cappuccino coffee for " + user); } }Creator Abstract Class –
CoffeeSelection.javapublic abstract class CoffeeSelection { public void serveCoffee(String user) { Coffee coffee = createCoffee(); // Factory Method coffee.brewCoffee(user); } protected abstract Coffee createCoffee(); }Concrete Creators –
EspressoFlavour.javaandCappuccinoFlavour.java
public class EspressoFlavour extends CoffeeSelection {
@Override
protected Coffee createCoffee() {
return new EspressoCoffee();
}
}
public class CappuccinoFlavour extends CoffeeSelection {
@Override
protected Coffee createCoffee() {
return new CappuccinoCoffee();
}
}
Factory Dispatcher –
CoffeeMachineFactory.javapublic class CoffeeMachineFactory { public static CoffeeSelection getMyCoffee(String type) throws Exception { if (type.equalsIgnoreCase("espresso")) { return new EspressoFlavour(); } else if (type.equalsIgnoreCase("cappuccino")) { return new CappuccinoFlavour(); } else { throw new Exception("Selected Coffee flavour not available"); } } }Client Code –
CoffeeShop.javapublic class CoffeeShop { public static void main(String[] args) throws Exception { CoffeeSelection espresso = CoffeeMachineFactory.getMyCoffee("espresso"); espresso.serveCoffee("Alice"); CoffeeSelection cappuccino = CoffeeMachineFactory.getMyCoffee("cappuccino"); cappuccino.serveCoffee("Bob"); } }✅ Output:
Brewing Espresso coffee for Alice Brewing Cappuccino coffee for Bob
🎯 What This Demonstrates
CoffeeSelectiondefines the factory method:createCoffee()Subclasses like
EspressoFlavourandCappuccinoFlavouroverride the factory method to provide specific product implementationsClient code (
CoffeeShop) interacts only with the abstract interface and doesn't worry about the creation logicThis allows us to add new coffee types in the future without changing existing code — a great example of the Open/Closed Principle (i.e, one of the five SOLID principles of object-oriented design- Open for extension but closed for modification)
🧠 Why Use the Factory Method Pattern?
👍 Advantages:
Encapsulates object creation logic
Promotes code reusability and clean architecture
Encourages polymorphism — client code uses the abstract type
Easy to extend — just add a new subclass and override the factory method
📌 When to Use It:
When you want to delegate the responsibility of instantiating objects to child classes
When the creation process might change depending on context or input
When working with frameworks or libraries that expect you to plug in behavior via subclassing
Want to see how this same example evolves into the Abstract Factory Pattern (for regional coffee experiences)? Stay tuned for Week 3!
🔜 Next up: The Abstract Factory Pattern!
“Next up: the Abstract Factory Pattern! We're continuing our journey through design patterns with clear, beginner-friendly explanations and practical examples.”
This pattern takes flexible object creation to the next level — it lets you create families of related objects without specifying their concrete classes. Whether you're building cross-platform UIs or themed product bundles, Abstract Factory helps ensure consistency and scalability across components.
Follow along each week as we demystify these patterns and help you build cleaner, modular, and maintainable code — one pattern at a time.
✅ Call to Action (CTA)
🚀 Want to level up your design pattern skills?
Subscribe or follow the series — we’ll walk through each pattern with examples, analogies, and real-world code you can use today.
Note: AI-generated Image




