> ## Documentation Index
> Fetch the complete documentation index at: https://akshanshgusain.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Factory Method Pattern

> Creational Patterns

<Note>
  [Python Code example](https://github.com/akshanshgusain/design_patterns_py/tree/master/creational/factoryMethod)
</Note>

## Definition

**“Factory Method pattern defines an interface/method (a.k.a. factory method) for creating an object, but lets subclasses
decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses”**

<Frame>
  <img src="https://mintcdn.com/akshanshgusain/U9KiYWNLHNn_ZtUv/lld/fundamentals/patterns/creational/images/factory-method-uml.jpeg?fit=max&auto=format&n=U9KiYWNLHNn_ZtUv&q=85&s=ef01fc68018f0eb144c5129d25ea7041" alt="factory-method" width="1783" height="1000" data-path="lld/fundamentals/patterns/creational/images/factory-method-uml.jpeg" />
</Frame>

## Explanation

You declare a factory method in a base creator class (or interface) (e.g., `createDocument()` in `Application`). Concrete
subclasses override it to return specific products (e.g., `SpreadsheetDocument`, `TextDocument`). Clients call the factory
method on the base class interface, but the actual subclass controls the product’s type. This decouples product creation
from client code.

## Code

In this example, Creator defines the factory method `factory_method()`, and its subclasses (`ConcreteCreator1`,
`ConcreteCreator2`) override this method to create specific products (`ConcreteProduct1`, `ConcreteProduct2`). The
client code uses a creator without knowing the exact product class.

```python theme={null}
from abc import ABC, abstractmethod

class Creator(ABC):
    @abstractmethod
    def factory_method(self):
        pass
    def some_operation(self) -> str:
        product = self.factory_method()
        return f"Creator: The same creator's code has just worked with {product.operation()}"

class ConcreteCreator1(Creator):
    def factory_method(self):
        return ConcreteProduct1()
class ConcreteCreator2(Creator):
    def factory_method(self):
        return ConcreteProduct2()

class Product(ABC):
    @abstractmethod
    def operation(self) -> str:
        pass
class ConcreteProduct1(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct1}"
class ConcreteProduct2(Product):
    def operation(self) -> str:
        return "{Result of the ConcreteProduct2}"

def client_code(creator: Creator) -> None:
    print(f"Client: Creator is {type(creator).__name__}. {creator.some_operation()}")

def main():
    print("App: Launched with the ConcreteCreator1.")
    client_code(ConcreteCreator1())
    print("\nApp: Launched with the ConcreteCreator2.")
    client_code(ConcreteCreator2())
    print()

if __name__ == "__main__":
    main()

```

## Analogy

A pizza store example: the base class PizzaStore defines orderPizza(type) which calls the abstract createPizza(type).
Subclasses like NYPizzaStore and ChicagoPizzaStore implement createPizza to return region-specific pizzas. The orderPizza
steps remain the same, while creation varies by subclass.

## Interview Insights

**Common uses**: When a class can’t anticipate the class of objects it must create. Common in frameworks: you extend a
base class and provide the object type. Also useful when you want to provide hooks for subclasses to supply products (
e.g. GUI toolkit creating platform-specific widgets).\
**Advantages**: Adheres to Open/Closed: new product types can be added by subclassing without modifying base code. Encapsulates object creation code.\
**Disadvantages**: Requires a new subclass for each product variant, leading to many classes. Adds complexity
(indirection) for simple cases.\\

## Alternate Explanation

### Problem Statement

When you have a class that needs to create objects, you often use new (in Python, just call the class). But hardcoding
which class to instantiate makes the code rigid and harder to extend or change.

**Imagine you're ordering food delivery:**

You don’t care which person prepares your food.

You just ask for a "`Pizza`" or a "`Burger`", and the restaurant has a method to decide how and who prepares it.

This “method” is the `Factory Method` — it decides which concrete class (Chef) will make your product (food).

```python Notification Example theme={null}
from abc import ABC, abstractmethod

# Step 1: Product Interface
class Notification(ABC):
    @abstractmethod
    def notify(self, message: str):
        pass

# Step 2: Concrete Products
class EmailNotification(Notification):
    def notify(self, message: str):
        print(f"Email: {message}")

class SMSNotification(Notification):
    def notify(self, message: str):
        print(f"SMS: {message}")

# Step 3: Creator (Abstract)
class NotificationSender(ABC):
    @abstractmethod
    def create_notification(self) -> Notification:
        """Factory method"""
        pass

    def send(self, message: str):
        # Uses the factory method
        notifier = self.create_notification()
        notifier.notify(message)

# Step 4: Concrete Creators
class EmailSender(NotificationSender):
    def create_notification(self) -> Notification:
        return EmailNotification()

class SMSSender(NotificationSender):
    def create_notification(self) -> Notification:
        return SMSNotification()

# Step 5: Client code
def client_code(sender: NotificationSender, message: str):
    sender.send(message)

# Usage
client_code(EmailSender(), "You've got mail!")
client_code(SMSSender(), "This is a text message.")

```
