ReviseAlgo Logo

Creational Patterns

Factory Method

Define an interface for creating an object, but let subclasses decide which class to instantiate

Last Updated: June 26, 2026 26 min read

Factory Method Pattern

Creator Hierarchy
«abstract»
NotificationFactory
+ createNotification(): Notification
EmailFactory
→ EmailNotification
SMSFactory
→ SMSNotification
Product Hierarchy
«interface»
Notification
+ send(message): void
EmailNotification
via SMTP
SMSNotification
via Twilio
Each Creator subclass produces its corresponding Product without the client knowing which concrete class is instantiated

1. Learning Objectives

  • Understand the core problem Factory Method solves and how it respects the Open/Closed Principle.
  • Differentiate between Simple Factory, Factory Method, and Abstract Factory.
  • Trace how dynamic method dispatch (vtables) handles polymorphic object instantiation at runtime.
  • Analyze parallel class hierarchies and how they align Creators and Products.
  • Implement type-safe, extensible hierarchies in Java, Python, and C++.

2. Problem & Naive Solution

Consider an application that processes alerts. Initially, it only needs to send Email Notifications. We implement an EmailNotification class.

Later, business requirements expand to support SMS Notifications and Push Notifications.

The Naive Solution

To handle multiple notification types, a developer might write a central controller containing a switch block checking enum values:

This introduces significant coupling:

  • Violates Open/Closed Principle: Adding a new channel (e.g., WhatsApp) forces us to modify the core dispatch() method, risking regressions.
  • Tight Coupling: The high-level NotificationManager depends directly on every concrete notification class (EmailNotification, SMSNotification), preventing clean code division.

3. Issues

If we instantiate objects directly in the client, it is impossible to swap product variants without rewriting core business flows. When object instantiation code is scattered across different client modules, updating class constructors requires changing multiple source files, making maintenance difficult.

4. Pattern Introduction & UML

The Factory Method Pattern resolves this by defining an abstract method for creating objects. Instead of instantiating products directly, creators delegate this responsibility to specialized subclasses:

  • Product Interface (Notification): Defines the contract that all concrete products must implement.
  • Concrete Products (EmailNotification, SMSNotification): Implement the product contract.
  • Creator Class (NotificationFactory): Declares the abstract factory method createNotification() and contains core business logic that operates on the product interface.
  • Concrete Creators (EmailFactory, SMSFactory): Override the factory method to return a specific concrete product instance.

5. Participants

  • Product (Notification): The abstract base/interface for the objects the factory method creates.
  • Concrete Product (EmailNotification): The concrete object type being instantiated.
  • Creator (NotificationFactory): Declares the factory method returning a Notification reference.
  • Concrete Creator (EmailFactory): Overrides the factory method to instantiate and return EmailNotification.

6. Theory (Comparison Matrix)

It is common to confuse different factory patterns. The matrix below clarifies their differences:

Pattern Structural Style Implementation Strategy Decoupling Target
Simple Factory Concrete class with a static method Uses an internal switch or if-else block to instantiate classes Isolates client code from the new operator
Factory Method Polymorphic abstract inheritance Subclasses override an abstract method to return a specific product Decouples core business logic from concrete product types (OCP compliant)
Abstract Factory Interface containing multiple factory methods A factory object instantiates families of related products Decouples client from product families (e.g., Windows UI vs. macOS UI components)

7. Syntax Explanation

Implementing the pattern requires defining abstract creators and overriding the factory method:

  • Java: Uses the abstract keyword for the factory method, forcing concrete subclass factories to implement it.
  • Python: Leverages the abc module, marking the factory method with @abstractmethod.
  • C++: Declares a pure virtual function (e.g. virtual std::unique_ptr<Notification> createNotification() = 0;). Using smart pointers prevents memory leaks and supports runtime polymorphism cleanly.

8. Step-by-Step Implementation

  1. Step 1: Create the abstract Product interface (e.g., Notification).
  2. Step 2: Implement concrete products (e.g., EmailNotification, SMSNotification) implementing the product interface.
  3. Step 3: Declare the abstract Creator class (e.g., NotificationFactory) containing the abstract factory method and any template methods that operate on the product.
  4. Step 4: Implement concrete creator classes (e.g., EmailFactory, SMSFactory) that override the factory method to return instances of their respective products.
  5. Step 5: Refactor client code to interact only with the abstract creator and product interfaces.

9. Complete Code (Mini Project)

10. Code Walkthrough

Let's review the key elements of the refactored code:

  • The client code operates strictly on abstract interfaces: NotificationFactory and Notification. It contains no direct references to concrete subclasses like EmailNotification or EmailFactory.
  • The deliver() method in the abstract creator encapsulates the business logic. It calls the abstract factory method createNotification(), deferring the instantiation decision to subclasses.
  • To support a new type of notification, we only need to implement a new product class (e.g. PushNotification) and a corresponding factory class (PushFactory). The existing creator and client code remains unmodified.

11. Execution Flow

  1. Creator Instantiation: The client instantiates a concrete creator class (e.g. EmailFactory) on the heap.
  2. Method Trigger: The client invokes the template method deliver("message") on the creator.
  3. Deferred Instantiation: The template method calls the factory method createNotification().
  4. Polymorphic Creation: The runtime uses dynamic dispatch to execute the overridden method in EmailFactory, instantiating the concrete product EmailNotification on the heap.
  5. Execution: The template method executes the business logic on the newly created product instance and returns.

12. Internal Working (JVM & Vtables)

At the virtual machine and compiler level, dynamic dispatch resolves the correct factory method using virtual tables:

  • Vtable Setup: During compilation, the compiler generates a virtual table (vtable) for the abstract creator class NotificationFactory. Subclasses override the vtable pointer offsets.
  • Method Resolution: When the template method calls createNotification(), the runtime checks the object header pointer to determine the concrete class type. It then performs a lookup in the subclass vtable to invoke the correct factory method.
  • Polymorphic Instantiation: The subclass factory method executes a standard memory allocation instruction (e.g. new in Java/C++), allocating memory on the heap and returning the pointer reference.

13. Complexity Analysis

  • Time Complexity: $O(1)$ constant time for instantiation and polymorphic delegation.
  • Space Complexity: $O(N + M)$ memory footprint, where $N$ is the number of concrete product classes and $M$ is the number of concrete creator classes. Splitting instantiations across separate classes increases compile-time metadata, but does not impact runtime execution speed.

14. Best Practices

  • Decouple Creator and Product Hierarchies: Maintain parallel class hierarchies. Avoid combining the creator and product logic into a single class hierarchy.
  • Enforce Constructor Encapsulation: Make concrete product constructors package-private or protected to prevent clients from bypassing the factories.
  • Use Simple Factory for simpler scenarios: If you do not need subclass flexibility or parallel class hierarchies, a Simple Factory (a single class with a static creation method) is cleaner and avoids subclass bloat.

15. Common Mistakes

  • Subclass Explosion: Creating a new creator subclass for every simple product variation. If product variants only differ in attributes rather than behavior, pass parameter arguments to a single factory instead.
  • Confusing Factory Method with Simple Factory: Calling a static helper method a "Factory Method." Factory Method relies on class inheritance and virtual method overriding.
  • Adding business logic to factory methods: Bloating the factory method with business validation or state tracking. Keep the factory method focused strictly on object instantiation.

16. Framework Usage

  • Java Calendar: The Calendar.getInstance() method behaves like a factory, returning a specific calendar subclass (e.g. GregorianCalendar) based on the system locale.
  • Java Collections Iterator: The iterator() method in Java collections (e.g. ArrayList.iterator(), HashSet.iterator()) is a classic Factory Method. The abstract collection interface defines the method, and each collection subclass overrides it to return a specialized iterator.
  • Spring FactoryBean: Spring's FactoryBean interface allows developers to customize bean instantiation by implementing a getObject() factory method.

17. Interview Discussion

Q: How does Factory Method promote the Open/Closed Principle?
Answer: By abstracting object creation. When adding a new product, we create a new product subclass and a new creator subclass. The existing creator interfaces, template methods, and client code remain unchanged.
Q: What is the main drawback of the Factory Method pattern?
Answer: Subclass explosion. For every new product class, the developer must also implement a corresponding creator subclass. This can quickly double the number of classes in the codebase.
Q: How can we prevent subclass explosion in the Factory Method pattern?
Answer: By using parameterized factory methods (passing an identifier to a single factory method that handles instantiation) or by using generic classes (e.g. template-based creators in C++).

18. Practice Exercises

  • Easy: Implement a simple DocumentFactory in Python that returns PDFDocument or WordDocument instances.
  • Medium: Design a C++ DatabaseConnectorFactory containing a template method connect(). Concrete factories should return connection handlers for MySQL and PostgreSQL.
  • Hard: Design a parameterized Factory Method in Java that uses reflection to dynamically load and register new product classes at runtime from a configuration file, avoiding subclass explosion.

19. Challenge Problem

Design a cross-platform GUI Widget Engine using the Factory Method pattern. The engine constructs buttons, checkboxes, and text inputs for Windows, macOS, and Linux. The central rendering loop operates on abstract widget contracts, completely isolated from operating system details. Write the implementation in Java, Python, or C++ and show how adding support for a new operating system requires zero changes to the core rendering loop.

20. Summary & Cheat Sheet

  • The Factory Method pattern defines an interface for creating objects, delegating instantiation to subclasses.
  • It promotes loose coupling by decoupling client code from concrete product classes.
  • It implements parallel class hierarchies matching creators to products.
  • The pattern supports the Open/Closed Principle by allowing new products to be added without modifying existing code.

21. Quiz

1. Which problem is solved by the Factory Method pattern?

A) Global instance synchronization race conditions
B) Hardcoded, tightly coupled object instantiations in client code (Correct)
C) Subclasses throwing exceptions for unimplemented parent methods

2. How does the Factory Method pattern delegate instantiation responsibility?

A) By using static database connection utilities
B) Through class inheritance, allowing subclasses to override an abstract factory method (Correct)
C) Using reflection to access private constructors directly

3. What is a key disadvantage of the Factory Method pattern?

A) It requires making all classes public
B) It prevents dynamic casting
C) Subclass explosion, requiring a new creator subclass for every product class (Correct)

4. How does Factory Method differ from Abstract Factory?

A) Factory Method creates a single product via inheritance; Abstract Factory creates families of related products via composition (Correct)
B) Factory Method uses static methods; Abstract Factory uses public fields
C) There is no difference between the two patterns

5. In Java collections, which method is a classic example of the Factory Method pattern?

A) add()
B) size()
C) iterator() (Correct)

6. What is a template method in the context of the Factory Method pattern?

A) A method in the creator class containing core business logic that operates on the product returned by the factory method (Correct)
B) A method that compiles C++ generic templates
C) A static helper method

7. Why are virtual destructors mandatory in C++ abstract product classes?

A) To speed up virtual lookup checks
B) To ensure concrete subclass resources are cleaned up correctly when deleted via base pointer references (Correct)
C) C++ virtual classes do not require destructors

8. Which SOLID principle is directly supported by the Factory Method pattern?

A) Single Responsibility Principle
B) Open/Closed Principle (Correct)
C) Liskov Substitution Principle

9. What is a parallel class hierarchy?

A) Two unrelated class hierarchies that execute in parallel threads
B) Mirroring creator and product hierarchies, linking each concrete creator subclass to a concrete product class (Correct)
C) Storing classes in parallel packages

10. When should a developer prefer Simple Factory over Factory Method?

A) When they want to enforce absolute immutability
B) When the object instantiation logic is simple and does not require subclassing flexibility (Correct)
C) When calling database connection APIs

22. Next Lesson Preview

In the next lesson, we will cover the Abstract Factory Pattern. We will learn how to create families of related or dependent objects without specifying their concrete classes!