Hubbry Logo
Factory method patternFactory method patternMain
Open search
Factory method pattern
Community hub
Factory method pattern
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
Contribute something
Factory method pattern
Factory method pattern
from Wikipedia

In object-oriented programming, the factory method pattern is a design pattern that uses factory methods to deal with the problem of creating objects without having to specify their exact classes. Rather than by calling a constructor, this is accomplished by invoking a factory method to create an object. Factory methods can be specified in an interface and implemented by subclasses or implemented in a base class and optionally overridden by subclasses. It is one of the 23 classic design patterns described in the book Design Patterns (often referred to as the "Gang of Four" or simply "GoF") and is subcategorized as a creational pattern.[1]

Overview

[edit]

The factory method design pattern solves problems such as:

  • How can an object's subclasses redefine its subsequent and distinct implementation? The pattern involves creation of a factory method within the superclass that defers the object's creation to a subclass's factory method.
  • How can an object's instantiation be deferred to a subclass? Create an object by calling a factory method instead of directly calling a constructor.

This enables the creation of subclasses that can change the way in which an object is created (for example, by redefining which class to instantiate).

Definition

[edit]

According to Design Patterns: Elements of Reusable Object-Oriented Software: "Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory method lets a class defer instantiation to subclasses."[2]

Creating an object often requires complex processes not appropriate to include within a composing object. The object's creation may lead to a significant duplication of code, may require information inaccessible to the composing object, may not provide a sufficient level of abstraction or may otherwise not be included in the composing object's concerns. The factory method design pattern handles these problems by defining a separate method for creating the objects, which subclasses can then override to specify the derived type of product that will be created.

The factory method pattern relies on inheritance, as object creation is delegated to subclasses that implement the factory method to create objects.[3] The pattern can also rely on the implementation of an interface.

Structure

[edit]

UML class diagram

[edit]
A sample UML class diagram for the Factory Method design pattern. [4]

In the above UML class diagram, the Creator class that requires a Product object does not instantiate the Product1 class directly. Instead, the Creator refers to a separate factoryMethod() to create a product object, which makes the Creator independent of the exact concrete class that is instantiated. Subclasses of Creator can redefine which class to instantiate. In this example, the Creator1 subclass implements the abstract factoryMethod() by instantiating the Product1 class.

Examples

[edit]

Structure

[edit]

A maze game may be played in two modes, one with regular rooms that are only connected with adjacent rooms, and one with magic rooms that allow players to be transported at random.

Room is the base class for a final product (MagicRoom or OrdinaryRoom). MazeGame declares the abstract factory method to produce such a base product. MagicRoom and OrdinaryRoom are subclasses of the base product implementing the final product. MagicMazeGame and OrdinaryMazeGame are subclasses of MazeGame implementing the factory method producing the final products. Factory methods thus decouple callers (MazeGame) from the implementation of the concrete classes. This makes the new operator redundant, allows adherence to the open–closed principle and makes the final product more flexible in the event of change.

Example implementations

[edit]

This C++23 implementation is based on the pre C++98 implementation in the Design Patterns book.[5]

import std;

using std::unique_ptr;

enum class ProductId: char {
    MINE, 
    YOURS
};

// defines the interface of objects the factory method creates.
class Product {
public:
    virtual void print() = 0;
    virtual ~Product() = default;
};

// implements the Product interface.
class ConcreteProductMINE: public Product {
public:
    void print() {
        std::println("this={} print MINE", this);
    }
};

// implements the Product interface.
class ConcreteProductYOURS: public Product {
public:
    void print() {
        std::println("this={} print YOURS", this);
    }
};

// declares the factory method, which returns an object of type Product.
class Creator {
public:
    virtual unique_ptr<Product> create(ProductId id) {
        switch (id) {
            case ProductId::MINE:
                return std::make_unique<ConcreteProductMINE>();
            case ProductId::YOURS:
                return std::make_unique<ConcreteProductYOURS>();
            // repeat for remaining products
            default:
                return nullptr;
        }
    }

    virtual ~Creator() = default;
};

int main(int argc, char* argv[]) {
    unique_ptr<Creator> creator = std::make_unique<Creator>();
    unique_ptr<Product> product = creator->create(ProductId::MINE);
    product->print();

    product = creator->create(ProductId::YOURS);
    product->print();
}

The program output is like

this=0x6e5e90 print MINE
this=0x6e62c0 print YOURS
// Empty vocabulary of actual object
public interface IPerson
{
    string GetName();
}

public class Villager : IPerson
{
    public string GetName()
    {
        return "Village Person";
    }
}

public class CityPerson : IPerson
{
    public string GetName()
    {
        return "City Person";
    }
}

public enum PersonType
{
    Rural,
    Urban
}

/// <summary>
/// Implementation of Factory - Used to create objects.
/// </summary>
public class PersonFactory
{
    public IPerson GetPerson(PersonType type)
    {
        switch (type)
        {
            case PersonType.Rural:
                return new Villager();
            case PersonType.Urban:
                return new CityPerson();
            default:
                throw new NotSupportedException();
        }
    }
}

The above code depicts the creation of an interface called IPerson and two implementations called Villager and CityPerson. Based on the type passed to the PersonFactory object, the original concrete object is returned as the interface IPerson.

A factory method is just an addition to the PersonFactory class. It creates the object of the class through interfaces but also allows the subclass to decide which class is instantiated.

public interface IProduct
{
    string GetName();
    bool SetPrice(double price);
}

public class Phone : IProduct
{
    private double _price;

    public string GetName()
    {
        return "Apple TouchPad";
    }

    public bool SetPrice(double price)
    {
        _price = price;
        return true;
    }
}

/* Almost same as Factory, just an additional exposure to do something with the created method */
public abstract class ProductAbstractFactory
{
    protected abstract IProduct MakeProduct();

    public IProduct GetObject() // Implementation of Factory Method.
    {
        return this.MakeProduct();
    }
}

public class PhoneConcreteFactory : ProductAbstractFactory
{
    protected override IProduct MakeProduct()
    {
        IProduct product = new Phone();
        // Do something with the object after receiving it
        product.SetPrice(20.30);
        return product;
    }
}

In this example, MakeProduct is used in concreteFactory. As a result, MakeProduct() may be invoked in order to retrieve it from the IProduct. Custom logic could run after the object is obtained in the concrete factory method. GetObject is made abstract in the factory interface.

This Java example is similar to one in the book Design Patterns.

The MazeGame uses Room but delegates the responsibility of creating Room objects to its subclasses that create the concrete classes. The regular game mode could use this template method:

public abstract class Room {
    abstract void connect(Room room);
}

public class MagicRoom extends Room {
    public void connect(Room room) {}
}

public class OrdinaryRoom extends Room {
    public void connect(Room room) {}
}

public abstract class MazeGame {
     private final List<Room> rooms = new ArrayList<>();

     public MazeGame() {
          Room room1 = makeRoom();
          Room room2 = makeRoom();
          room1.connect(room2);
          rooms.add(room1);
          rooms.add(room2);
     }

     abstract protected Room makeRoom();
}

The MazeGame constructor is a template method that adds some common logic. It refers to the makeRoom() factory method that encapsulates the creation of rooms such that other rooms can be used in a subclass. To implement the other game mode that has magic rooms, the makeRoom method may be overridden:

public class MagicMazeGame extends MazeGame {
    @Override
    protected MagicRoom makeRoom() {
        return new MagicRoom();
    }
}

public class OrdinaryMazeGame extends MazeGame {
    @Override
    protected OrdinaryRoom makeRoom() {
        return new OrdinaryRoom();
    }
}

MazeGame ordinaryGame = new OrdinaryMazeGame();
MazeGame magicGame = new MagicMazeGame();

This PHP example shows interface implementations instead of subclassing (however, the same can be achieved through subclassing). The factory method can also be defined as publicand called directly by the client code (in contrast to the previous Java example).

/* Factory and car interfaces */

interface CarFactory
{
    public function makeCar(): Car;
}

interface Car
{
    public function getType(): string;
}

/* Concrete implementations of the factory and car */

class SedanFactory implements CarFactory
{
    public function makeCar(): Car
    {
        return new Sedan();
    }
}

class Sedan implements Car
{
    public function getType(): string
    {
        return 'Sedan';
    }
}

/* Client */

$factory = new SedanFactory();
$car = $factory->makeCar();
print $car->getType();

This Python example employs the same as did the previous Java example.

from abc import ABC, abstractmethod


class MazeGame(ABC):
    def __init__(self) -> None:
        self.rooms = []
        self._prepare_rooms()

    def _prepare_rooms(self) -> None:
        room1 = self.make_room()
        room2 = self.make_room()

        room1.connect(room2)
        self.rooms.append(room1)
        self.rooms.append(room2)

    def play(self) -> None:
        print(f"Playing using {self.rooms[0]}")

    @abstractmethod
    def make_room(self):
        raise NotImplementedError("You should implement this!")


class MagicMazeGame(MazeGame):
    def make_room(self) -> "MagicRoom":
        return MagicRoom()


class OrdinaryMazeGame(MazeGame):
    def make_room(self) -> "OrdinaryRoom":
        return OrdinaryRoom()


class Room(ABC):
    def __init__(self) -> None:
        self.connected_rooms = []

    def connect(self, room: "Room") -> None:
        self.connected_rooms.append(room)


class MagicRoom(Room):
    def __str__(self) -> str:
        return "Magic room"


class OrdinaryRoom(Room):
    def __str__(self) -> str:
        return "Ordinary room"


ordinaryGame = OrdinaryMazeGame()
ordinaryGame.play()

magicGame = MagicMazeGame()
magicGame.play()

Uses

[edit]

See also

[edit]

Notes

[edit]

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
The Factory Method pattern is a creational design pattern in object-oriented programming that defines an interface or abstract method for creating objects in a superclass, while allowing subclasses to decide which specific class to instantiate, thereby promoting flexibility in object creation without tightly coupling the client code to concrete classes. Introduced in the seminal 1994 book Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (commonly known as the Gang of Four or GoF), the pattern addresses the need to encapsulate object creation logic, enabling systems to be extended with new types without modifying existing code. At its core, the Factory Method pattern involves four main components: a Product interface defining the object's type, Concrete Products as specific implementations, a Creator that declares the factory method returning a Product, and Concrete Creators that override the method to return instances of Concrete Products. This structure adheres to key principles like the Open-Closed Principle (open for extension, closed for modification) and the Single Responsibility Principle by isolating instantiation responsibilities. The pattern is particularly useful in scenarios requiring polymorphic object creation, such as framework development or when the exact type of object is determined at runtime, as seen in applications like Java RMI where factories manage remote object instantiation to reduce coupling and improve scalability. Key benefits include avoiding direct dependencies on concrete classes, which enhances code reusability and maintainability, and supporting the creation of families of related objects without specifying their exact classes upfront. Unlike the simpler Abstract Factory pattern, which deals with families of products, Factory Method focuses on a single product's creation while deferring the decision to subclasses, making it ideal for hierarchical extensions in software design. Overall, it remains a foundational technique in modern object-oriented languages like Java, C++, and Python for building robust, extensible systems.

Introduction

Overview

The Factory Method pattern is a creational design pattern in object-oriented software design that provides a way to delegate the instantiation of objects to subclasses, enabling greater flexibility in the types of objects created without tightly coupling the creator to specific concrete classes. This pattern was formally introduced in 1994 in the influential book Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides—collectively known as the Gang of Four (GoF)—as one of the original 23 reusable design patterns cataloged therein. The book emphasized patterns as proven solutions to common problems in object-oriented design, drawing from the authors' experiences in industry and academia, including at companies like IBM. At its core, the Factory Method pattern defines an interface or abstract method for creating an object, but lets subclasses override this method to specify the exact type of object to instantiate, thereby encapsulating creation logic and supporting polymorphic behavior across related object families. By isolating object creation from usage, the pattern improves code maintainability and extensibility, adhering to the open-closed principle—which advocates designing modules that are open for extension but closed for modification—thus allowing new subclasses to be added without altering existing client code.

Motivation

In object-oriented systems, client code that directly instantiates concrete classes creates tight coupling between the clients and those specific implementations, making it difficult to replace or vary the objects without widespread code changes. This issue becomes prominent when systems need to produce different types of objects based on runtime context or configuration, such as creating platform-specific user interface components—like buttons or menus—that differ between desktop and mobile environments. The challenge intensifies in larger frameworks or applications, where a central component is responsible for object creation but must support extensibility without knowing the exact concrete classes in advance. For example, a document management framework might require instantiating various document subtypes (e.g., text or graphical), but embedding direct calls to concrete constructors in the framework code ties it rigidly to those classes, complicating reuse and adaptation for new document types. These problems originate from monolithic creation logic concentrated in client or framework methods, where any alteration to the created object types propagates modifications across the entire codebase, often requiring recompilation and testing of unrelated parts. This approach contravenes the open-closed principle by closing the system to extension without modification. Assuming familiarity with basic object-oriented concepts like inheritance and polymorphism, direct instantiation undermines their benefits by preventing code from operating solely through abstract interfaces, thus reducing overall flexibility and maintainability.

Core Concepts

Definition

The Factory Method pattern is a creational design pattern defined as follows: "Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses." This definition originates from the seminal work on design patterns by Gamma et al., establishing the pattern's core mechanism for encapsulating object creation while promoting flexibility through inheritance. Central to the pattern are four key participants: the Creator, which declares the factory method responsible for returning an object conforming to the Product interface; the ConcreteCreator, which provides a concrete implementation of the factory method to instantiate a specific ConcreteProduct; the Product, which defines the abstract interface for the objects to be created; and the ConcreteProduct, which implements the Product interface to provide the actual functionality. These components enable the pattern to abstract the instantiation logic, allowing subclasses to override the factory method for varying product types without altering the creator's core behavior. As a creational pattern, the Factory Method specifically emphasizes subclassing as the primary means to control and vary the instantiation process, distinguishing it from other creational approaches that might rely on composition or parameterization.

Intent and Applicability

The Factory Method pattern's primary intent is to define an interface for creating an object while allowing subclasses to determine the exact class to instantiate, thereby deferring instantiation decisions to subclasses and promoting extensibility without altering existing code. This approach enables a creator class to specify the general kind of product it uses through an abstract type, isolating the client from concrete implementations and facilitating the substitution of related object families. The pattern is applicable in scenarios where a class cannot foresee the specific types of objects it must create, such as when the object types vary based on runtime conditions or configuration. It is also suitable when a class intends for its subclasses to specify the precise objects to be created, thereby localizing object creation logic within the subclass hierarchy. Additionally, employ the pattern to delegate the responsibility of object creation to child classes, which helps in encapsulating creation knowledge and avoiding direct dependencies on concrete classes. Among the consequences of applying the Factory Method pattern, it effectively isolates client code from concrete classes, reducing coupling and enhancing flexibility in object creation. However, this isolation can introduce additional complexity into the class hierarchy, as each new product type may require corresponding creator subclasses, potentially increasing the number of classes in the design. This trade-off supports adherence to the open-closed principle by allowing extension through subclassing without modifying the base creator.

Design Structure

Key Components

The Factory Method pattern revolves around four primary participants, each with distinct roles that enable flexible object creation while promoting loose coupling in object-oriented designs. These components work together to defer the instantiation decision to subclasses, allowing the system to create objects without tightly binding the client code to specific classes. The Creator is an abstract class or interface that declares the factory method, which is responsible for returning an object of type Product. This method serves as the central point for object creation, and the Creator may also provide a default implementation of the factory method that returns a default concrete product instance if no subclass overrides it. By centralizing the creation logic in this declaration, the Creator ensures that all subclasses follow a consistent interface for instantiation. The ConcreteCreator is a subclass of the Creator that provides a specific implementation by overriding the factory method to return instances of particular ConcreteProduct classes. This participant embodies the customization aspect of the pattern, as different ConcreteCreators can produce different types of products tailored to their needs, thereby extending the base creation behavior without altering the Creator's interface. The Product defines an interface or abstract class that specifies the common operations and attributes for all objects created by the factory method. It establishes the contract that all concrete products must adhere to, ensuring interchangeability and polymorphism among the created objects regardless of their specific implementations. The ConcreteProduct implements the Product interface, delivering the concrete functionality and behavior for a specific type of object. Multiple ConcreteProduct classes can exist, each corresponding to variations produced by different ConcreteCreators, allowing the system to support diverse object types through a unified interface. In terms of interactions, clients interact solely with the Creator and its factory method to request products, remaining unaware of the specific ConcreteProduct classes involved. The factory method in the ConcreteCreator handles the actual instantiation, encapsulating the creation details and enabling the substitution of product types at runtime or through subclassing, which aligns with object-oriented polymorphism principles.

UML Class Diagram

The UML class diagram for the Factory Method pattern depicts the static structure involving four primary elements: an abstract Creator class, a ConcreteCreator class, an abstract Product interface or class, and a ConcreteProduct class. The Creator is represented as an abstract class containing an abstract factory method, declared with a return type of Product, which serves as the interface for creating objects without specifying their concrete classes. The ConcreteCreator extends the Creator via an inheritance relationship (generalization arrow in UML), overriding the factoryMethod to instantiate and return a specific ConcreteProduct instance, such as new ConcreteProduct(). The Product is shown as an abstract class or interface defining the common operations that all concrete products must implement, with no direct dependency on the Creator in the diagram. The ConcreteProduct realizes or extends the Product through another inheritance or realization relationship, providing the specific implementation of those operations. Key relationships include the inheritance from Creator to ConcreteCreator and from Product to ConcreteProduct, along with the factoryMethod's return type covariance to Product, ensuring type safety. Additionally, the Creator may include other abstract or concrete operations that utilize the product returned by the factoryMethod, illustrated as method signatures within the Creator class. Variations in the diagram account for flexibility in the Creator's factoryMethod implementation; it may provide a default (non-abstract) version that returns a null, default product, or delegates to subclasses, rather than leaving it purely abstract. This optional concrete implementation is denoted in UML by a non-italicized method signature in the Creator, allowing subclasses to optionally override it. Multiple ConcreteCreator and ConcreteProduct pairs can be shown in extended diagrams to illustrate scalability, connected via parallel inheritance arrows.

+--------------------------------+ +-------------------+ | <<abstract>> | | <<interface>> | | Creator | | Product | +--------------------------------+ +-------------------+ | + factoryMethod(): Product | | + operation() | +--------------------------------+ +-------------------+ ^ ^ | | extends realizes +--------------------------------+ +-------------------+ | ConcreteCreator | | ConcreteProduct | +--------------------------------+ +-------------------+ | + factoryMethod(): Product | | + operation() | +--------------------------------+ +-------------------+

+--------------------------------+ +-------------------+ | <<abstract>> | | <<interface>> | | Creator | | Product | +--------------------------------+ +-------------------+ | + factoryMethod(): Product | | + operation() | +--------------------------------+ +-------------------+ ^ ^ | | extends realizes +--------------------------------+ +-------------------+ | ConcreteCreator | | ConcreteProduct | +--------------------------------+ +-------------------+ | + factoryMethod(): Product | | + operation() | +--------------------------------+ +-------------------+

This ASCII diagram is an approximation adapted from standard UML representations in the cited sources (e.g., Refactoring.Guru and Visual Paradigm tutorials), with corrected notation for the class inheritance relationship (shown here as "extends" for clarity in text form; standard graphical UML uses an unlabeled generalization arrow).

Implementation Approaches

General Algorithm

The general algorithm of the Factory Method pattern follows a structured runtime flow centered on deferred object creation through subclass polymorphism. The process begins when a client invokes the factoryMethod() on an instance of the Creator class or one of its subclasses. This call triggers the execution of the overridden factoryMethod() in a ConcreteCreator, which instantiates and returns an appropriate ConcreteProduct instance. The client then interacts with the returned object solely through the abstract Product interface, enabling polymorphic behavior without direct dependency on concrete types. Optionally, the Creator itself may call factoryMethod() internally within other operations to obtain and utilize a Product, ensuring consistent product creation across the class hierarchy. The following pseudocode illustrates the integration of the factory method into the Creator's operations:

abstract class Creator { abstract Product factoryMethod(); void someOperation() { Product product = factoryMethod(); // Perform operations using the product product.use(); } } class ConcreteCreator extends Creator { Product factoryMethod() { return new ConcreteProduct(); } }

abstract class Creator { abstract Product factoryMethod(); void someOperation() { Product product = factoryMethod(); // Perform operations using the product product.use(); } } class ConcreteCreator extends Creator { Product factoryMethod() { return new ConcreteProduct(); } }

This design promotes loose coupling, as the factoryMethod() return type is declared as the abstract Product, allowing interchangeable concrete implementations without altering client or creator code.

Language-Specific Examples

The Factory Method pattern can be implemented in various programming languages, adapting to their specific features such as abstract classes, interfaces, and typing systems. Below are representative examples in Java, Python, and C#, demonstrating how the pattern encapsulates object creation while allowing subclasses to decide the concrete type returned by the factory method. These implementations follow the general algorithm of defining an abstract creator with a factory method that returns a product, with concrete creators overriding to produce specific products.

Java Implementation

In Java, the pattern leverages abstract classes and interfaces to define the creator and product hierarchies. A common example involves creating image readers for different formats, where an abstract ImageReaderCreator declares the createImageReader() factory method, and concrete subclasses like JPEGReaderCreator and GIFReaderCreator implement it to return the appropriate reader. The client code invokes the factory method without specifying the concrete product class, promoting flexibility.

java

// Product interface interface ImageReader { void readImage(); } // Concrete Products class JPEGReader implements ImageReader { public void readImage() { System.out.println("Reading JPEG image"); } } class GIFReader implements ImageReader { public void readImage() { System.out.println("Reading GIF image"); } } // Abstract Creator abstract class ImageReaderCreator { public abstract ImageReader createImageReader(); // Other methods that use the product public void read() { ImageReader reader = createImageReader(); reader.readImage(); } } // Concrete Creators class JPEGReaderCreator extends ImageReaderCreator { public ImageReader createImageReader() { return new JPEGReader(); } } class GIFReaderCreator extends ImageReaderCreator { public ImageReader createImageReader() { return new GIFReader(); } } // Client code public class Client { public static void main(String[] args) { ImageReaderCreator creator = new JPEGReaderCreator(); // or GIFReaderCreator creator.read(); } }

// Product interface interface ImageReader { void readImage(); } // Concrete Products class JPEGReader implements ImageReader { public void readImage() { System.out.println("Reading JPEG image"); } } class GIFReader implements ImageReader { public void readImage() { System.out.println("Reading GIF image"); } } // Abstract Creator abstract class ImageReaderCreator { public abstract ImageReader createImageReader(); // Other methods that use the product public void read() { ImageReader reader = createImageReader(); reader.readImage(); } } // Concrete Creators class JPEGReaderCreator extends ImageReaderCreator { public ImageReader createImageReader() { return new JPEGReader(); } } class GIFReaderCreator extends ImageReaderCreator { public ImageReader createImageReader() { return new GIFReader(); } } // Client code public class Client { public static void main(String[] args) { ImageReaderCreator creator = new JPEGReaderCreator(); // or GIFReaderCreator creator.read(); } }

This example illustrates how Java's strong typing and inheritance enforce the pattern's structure, ensuring type safety at compile time.

Python Implementation

Python's dynamic typing and abstract base classes (from the abc module) enable a more flexible Factory Method implementation. Here, an abstract Creator class defines the factory_method() that returns a product adhering to a protocol (duck typing), with concrete creators overriding it to instantiate specific products, such as document creators for different formats. The client uses the creator polymorphically, relying on runtime behavior.

python

from abc import ABC, abstractmethod # Product protocol (no formal interface, duck typing) class Product(ABC): @abstractmethod def operation(self): pass # Concrete Products class ConcreteProductA(Product): def operation(self): return "Result of ConcreteProductA" class ConcreteProductB(Product): def operation(self): return "Result of ConcreteProductB" # Abstract Creator class Creator(ABC): @abstractmethod def factory_method(self) -> Product: pass def some_operation(self) -> str: product = self.factory_method() result = f"Creator: The result is {product.operation()}" return result # Concrete Creators class ConcreteCreatorA(Creator): def factory_method(self) -> Product: return ConcreteProductA() class ConcreteCreatorB(Creator): def factory_method(self) -> Product: return ConcreteProductB() # Client code if __name__ == "__main__": creator = ConcreteCreatorA() # or ConcreteCreatorB print(creator.some_operation())

from abc import ABC, abstractmethod # Product protocol (no formal interface, duck typing) class Product(ABC): @abstractmethod def operation(self): pass # Concrete Products class ConcreteProductA(Product): def operation(self): return "Result of ConcreteProductA" class ConcreteProductB(Product): def operation(self): return "Result of ConcreteProductB" # Abstract Creator class Creator(ABC): @abstractmethod def factory_method(self) -> Product: pass def some_operation(self) -> str: product = self.factory_method() result = f"Creator: The result is {product.operation()}" return result # Concrete Creators class ConcreteCreatorA(Creator): def factory_method(self) -> Product: return ConcreteProductA() class ConcreteCreatorB(Creator): def factory_method(self) -> Product: return ConcreteProductB() # Client code if __name__ == "__main__": creator = ConcreteCreatorA() # or ConcreteCreatorB print(creator.some_operation())

Python's lack of enforced interfaces allows duck typing, where products are interchangeable based on method availability rather than inheritance, simplifying the pattern while maintaining extensibility.

C# Implementation

In C#, the pattern typically uses interfaces for products and abstract classes for creators, with virtual or abstract factory methods overridden in subclasses. For instance, an IProduct interface defines the product behavior, an abstract Creator class declares the virtual CreateProduct() method, and concrete creators like ConcreteCreatorA override it to return specific products. The client interacts with the abstract creator, deferring instantiation details.

csharp

// Product interface public interface IProduct { string Operation(); } // Concrete Products public class ConcreteProductA : IProduct { public string Operation() { return "{Result of the ConcreteProduct A}"; } } public class ConcreteProductB : IProduct { public string Operation() { return "{Result of the ConcreteProduct B}"; } } // Abstract Creator public abstract class Creator { public abstract IProduct CreateProduct(); // Factory method public string SomeOperation() { var product = CreateProduct(); var result = $"Creator: The result is {product.Operation()}"; return result; } } // Concrete Creators public class ConcreteCreatorA : Creator { public override IProduct CreateProduct() { return new ConcreteProductA(); } } public class ConcreteCreatorB : Creator { public override IProduct CreateProduct() { return new ConcreteProductB(); } } // Client code class Client { static void Main() { Creator creator = new ConcreteCreatorA(); // or new ConcreteCreatorB() Console.WriteLine(creator.SomeOperation()); } }

// Product interface public interface IProduct { string Operation(); } // Concrete Products public class ConcreteProductA : IProduct { public string Operation() { return "{Result of the ConcreteProduct A}"; } } public class ConcreteProductB : IProduct { public string Operation() { return "{Result of the ConcreteProduct B}"; } } // Abstract Creator public abstract class Creator { public abstract IProduct CreateProduct(); // Factory method public string SomeOperation() { var product = CreateProduct(); var result = $"Creator: The result is {product.Operation()}"; return result; } } // Concrete Creators public class ConcreteCreatorA : Creator { public override IProduct CreateProduct() { return new ConcreteProductA(); } } public class ConcreteCreatorB : Creator { public override IProduct CreateProduct() { return new ConcreteProductB(); } } // Client code class Client { static void Main() { Creator creator = new ConcreteCreatorA(); // or new ConcreteCreatorB() Console.WriteLine(creator.SomeOperation()); } }

C#'s support for interfaces and virtual methods aligns closely with the pattern's requirements, enabling compile-time polymorphism and integration with frameworks like dependency injection. These language-specific adaptations highlight how the Factory Method pattern accommodates static vs. dynamic typing and inheritance models: Java and C# emphasize explicit interfaces for type safety, while Python relies on conventions and ABCs for flexibility without rigid hierarchies.

Practical Applications

Common Use Cases

The Factory Method pattern finds frequent application in scenarios where object creation needs to be deferred to subclasses, aligning with its intent to define an interface for creating objects while allowing subclasses to decide the concrete type instantiated. In GUI frameworks, the pattern enables the creation of platform-specific widgets, such as buttons or dialogs tailored to Windows versus macOS environments, through a common creator class that subclasses override to produce the appropriate implementation. For document processing, factory methods are used to generate parsers or handlers for diverse file formats, like PDF or DOC, where a base creator defines the interface and subclasses specify the exact parser type based on the input format. In game development, the pattern supports the dynamic generation of entities such as enemies or items, with level-specific subclasses determining the concrete object type to spawn, thereby decoupling creation logic from the core game engine. Framework extensibility often employs the Factory Method to allow plugins or extensions to supply custom object creators without modifying the core framework code, as seen in systems where a factory method registers subclasses to instantiate variation-specific objects.

Real-World Scenarios

In Java's Abstract Window Toolkit (AWT) and Swing frameworks, the Factory Method pattern is employed within the LookAndFeel mechanism to create platform- or theme-specific user interface components without tightly coupling the application code to concrete implementations. LookAndFeel subclasses, such as MetalLookAndFeel or NimbusLookAndFeel, provide component-specific UI factories registered in UIDefaults, enabling the UIManager to instantiate appropriate UI delegates (e.g., for buttons, menus) based on the active look and feel. This approach allows developers to write portable GUI code that delegates component creation to the UIManager, as seen in the getUI method producing widgets with consistent behavior across environments. The .NET Framework utilizes the Factory Method pattern in its ADO.NET data access layer through the DbProviderFactories class, which serves as a central factory for creating database provider-specific connection objects. For instance, it instantiates SqlConnection for SQL Server or OracleConnection for Oracle databases based on a provider-invariant name and connection string, allowing applications to remain agnostic to the underlying data source while supporting multiple providers via a single API. This design, introduced in .NET Framework 2.0, promotes extensibility by enabling new database providers to be integrated without modifying client code, as the factory methods return concrete instances derived from abstract base classes like DbConnection. Logging libraries such as Apache Log4j 2 apply the Factory Method pattern via the @PluginFactory annotation to instantiate appenders—components responsible for outputting log events to various destinations like files, consoles, or databases. Custom or built-in appenders, such as FileAppender or ConsoleAppender, are created through factory methods declared in plugin classes, which parse configuration parameters and return configured instances during Log4j's initialization phase. This mechanism supports dynamic plugin loading and configuration flexibility, ensuring that log output handlers are produced according to the application's XML or properties file settings without direct instantiation in user code. In open-source projects like Android's print framework, the Factory Method pattern can be used by applications to create device- or content-specific PrintDocumentAdapter implementations for handling custom print jobs. Developers implement subclasses of PrintDocumentAdapter to manage layout and rendering based on content type (e.g., PDFs or images), while the PrintManager service orchestrates the print job using the provided adapter, ensuring compatibility across diverse Android devices by isolating print logic from the core application.

Comparisons and Variations

Versus Abstract Factory

The Factory Method pattern and the Abstract Factory pattern are both creational design patterns that encapsulate object creation, but they differ fundamentally in scope and intent. The Factory Method defines a single method in an abstract creator class for instantiating one type of product, allowing subclasses to override it and specify the concrete class to be created. In contrast, the Abstract Factory provides an interface with multiple factory methods, each responsible for creating a different but related product, enabling the production of entire families of interdependent objects without specifying their concrete classes. This distinction arises from the Factory Method's focus on isolating the creation logic for a single product hierarchy, while the Abstract Factory emphasizes consistency across multiple related product hierarchies. Choosing between the two patterns depends on the complexity of the object relationships in the system. The Factory Method is preferable for scenarios involving simple class hierarchies where only one product type varies, such as when a framework needs to delegate the instantiation of a specific component to subclasses without anticipating the exact type. It suits cases like creating different types of documents in an application, where the creator class has a single createDocument method overridden by subclasses. Conversely, the Abstract Factory is ideal when the system must ensure compatibility and uniformity among families of related products, such as in GUI toolkits that require matching sets of widgets (e.g., buttons, menus, and scrollbars) for different operating systems. Here, the abstract factory interface declares methods like createButton() and createMenu(), implemented by concrete factories for each platform. In terms of trade-offs, the Factory Method offers simplicity and ease of extension through inheritance, making it less overhead for targeted creation needs, though it can lead to a proliferation of subclasses if overused. The Abstract Factory, while more comprehensive for maintaining product family integrity, introduces greater complexity due to the need to define and manage multiple parallel hierarchies, potentially complicating maintenance in systems without strong interdependencies. Factory Methods are often used to implement Abstract Factories, blending the patterns when a single product's creation requires family-wide coordination. For example, a Factory Method might be employed in a button creator class with a single createButton method, overridden by subclasses to produce Windows or macOS buttons, focusing solely on that one product type. In comparison, an Abstract Factory for a UI theme would include methods for creating buttons, scrollbars, and windows together, ensuring all elements adhere to the same style (e.g., a "dark mode" family), thus coordinating an entire set of related components.

Versus Simple Factory and Prototype

The Factory Method pattern differs from the Simple Factory in its structural approach and adherence to design principles. While the Simple Factory employs a single class containing a creation method that uses conditional logic, such as a switch statement, to instantiate different product types based on input parameters, the Factory Method defines an abstract creation method in a superclass or interface, which concrete subclasses override to specify the exact object type returned. This inheritance-based mechanism in Factory Method allows for extension without modifying existing code, aligning with the Open-Closed Principle, whereas the Simple Factory violates this principle because adding new product types requires altering the conditional logic within the single factory class. In contrast to the Prototype pattern, the Factory Method relies on subclassing to determine object creation, enabling customization through inheritance hierarchies where each subclass implements its own factory method to produce specific variants. The Prototype pattern, however, avoids extensive subclassing by allowing objects to be created through cloning an existing prototype instance, which is particularly advantageous when object initialization is computationally expensive or involves complex configurations that are easier to copy than to reconstruct from scratch. Cloning in Prototype requires careful handling of deep copies to ensure independence from the original, but it supports runtime variations without predefined class hierarchies. The choice between these patterns depends on the system's needs: Factory Method is suitable for scenarios with established class hierarchies where extensibility via inheritance is desired, Simple Factory suffices for systems with a limited number of product variants and minimal extension requirements, and Prototype excels in cases demanding runtime object customization or avoidance of subclass proliferation. One limitation of the Factory Method is its potential to cause class explosion in large hierarchies, as each new product type necessitates a corresponding factory subclass, unlike the Prototype's instance-based approach that reuses a single class for multiple clones.

Benefits and Limitations

Advantages

The Factory Method pattern promotes adherence to the open-closed principle, enabling software entities to be open for extension through subclassing while remaining closed to modification of existing code. This allows developers to introduce new types of objects by creating additional creator subclasses without altering the core creator class or client code that relies on it. By defining an interface for object creation and delegating instantiation to subclasses, the pattern fosters loose coupling between clients and concrete product classes. Clients interact solely with abstract interfaces, insulating them from specific implementation details and reducing dependencies. This decoupling simplifies unit testing—such as by mocking factory methods—and enhances overall maintainability, as changes to concrete products do not propagate to client code. The pattern provides significant flexibility for evolving systems, permitting the addition of new product variants through simple subclass extensions rather than refactoring widespread instantiation logic. This extensibility supports scalable architectures where requirements for object types may change over time, without necessitating client-side modifications. Furthermore, it upholds the single responsibility principle by isolating object creation logic into dedicated factory methods, separating concerns from the business logic that utilizes those objects. This cleaner separation improves code readability and organization. In modern frameworks like Spring, the pattern manifests in the BeanFactory interface, which implements a sophisticated factory mechanism to enable dependency injection; this decouples configuration and dependency resolution from application code, allowing dynamic bean creation and wiring without hardcoded instantiations.

Disadvantages

One significant limitation of the Factory Method pattern is the potential for class proliferation, as each concrete product variant typically necessitates a corresponding concrete creator subclass to override the factory method. This can result in a parallel hierarchy of subclasses for creators that mirrors the product hierarchy, exponentially increasing the number of classes in the system as product types expand. The pattern introduces additional abstraction layers through interfaces and subclasses, which can impose unnecessary complexity in simpler scenarios where direct object instantiation suffices without polymorphic creation logic. In small-scale applications or cases with minimal product variations, this overhead may over-engineer the design, making the codebase harder to understand and maintain without providing proportional benefits. Factory Method heavily relies on inheritance to enable subclasses to customize object creation, which can introduce rigidity, particularly in languages like Java that support only single inheritance and limit a class's ability to extend multiple hierarchies. This dependency contrasts with modern object-oriented practices that emphasize composition over inheritance to achieve greater flexibility and avoid the fragility of deep inheritance trees, a shift prominent in post-2010 software engineering literature. To mitigate these issues, such as subclass proliferation, the Factory Method can be combined with the Prototype pattern, where objects are cloned from prototypes rather than created via subclassed factories, reducing the need for extensive creator hierarchies while preserving runtime flexibility.

References

Add your contribution
Related Hubs
Contribute something
User Avatar
No comments yet.