Factory Method Pattern

The Factory Method is a creational design pattern that defines an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. It promotes loose coupling by delegating the instantiation logic to subclasses.

Key Principles

Structure

Python Example: Shape Factory

from abc import ABC, abstractmethod
import math

# Product Interface
class Shape(ABC):
    @abstractmethod
    def area(self) -> float:
        pass

# Concrete Products
class Circle(Shape):
    def __init__(self, radius: float):
        self.radius = radius

    def area(self) -> float:
        return math.pi * self.radius ** 2

class Rectangle(Shape):
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def area(self) -> float:
        return self.width * self.height

class Square(Shape):
    def __init__(self, side: float):
        self.side = side

    def area(self) -> float:
        return self.side ** 2

# Creator (Factory) with Factory Method
class ShapeFactory(ABC):
    @abstractmethod
    def create_shape(self) -> Shape:
        pass

    # Template method using the factory
    def compute_area(self) -> float:
        shape = self.create_shape()
        return shape.area()

# Concrete Creators
class CircleFactory(ShapeFactory):
    def __init__(self, radius: float):
        self.radius = radius

    def create_shape(self) -> Shape:
        return Circle(self.radius)

class RectangleFactory(ShapeFactory):
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def create_shape(self) -> Shape:
        return Rectangle(self.width, self.height)

class SquareFactory(ShapeFactory):
    def __init__(self, side: float):
        self.side = side

    def create_shape(self) -> Shape:
        return Square(self.side)

# Usage (client code)
if __name__ == "__main__":
    circle = CircleFactory(radius=5).compute_area()
    rectangle = RectangleFactory(width=4, height=6).compute_area()
    square = SquareFactory(side=3).compute_area()

    print(f"Circle area: {circle:.2f}")      # ~78.54
    print(f"Rectangle area: {rectangle}")   # 24
    print(f"Square area: {square}")         # 9

When to Use Factory Method

Summary: Factory Method lets subclasses decide which object to instantiate, keeping client code decoupled from concrete classes.