Factory Pattern¶
Category: Creational Pattern
Overview¶
Define an interface for creating objects, but let subclasses or factory methods decide which class to instantiate. This pattern encapsulates object creation logic, making it easier to manage and modify instantiation without coupling code to specific classes.
Usage Guidelines¶
Use when:
- Multiple related types exist with a common interface and instances need to be created based on runtime conditions
- Object creation requires configuration, validation, or complex initialization logic
- Client code should be decoupled from concrete class implementations
- You need to easily substitute mock objects during testing
Avoid when:
- Creating objects is straightforward with no special logic required
- Only one class needs to be instantiated
- The added indirection doesn't provide meaningful benefits
- Performance overhead is unacceptable for critical operations
Implementation¶
from abc import ABC, abstractmethod
# Product Interface
class Animal(ABC):
@abstractmethod
def speak(self) -> str:
pass
# Concrete Products
class Dog(Animal):
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
return f"{self.name} says woof!"
class Cat(Animal):
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
return f"{self.name} says meow!"
# Factory
class AnimalFactory:
def get_animal(self, animal_type: str, name: str) -> Animal:
if animal_type == "dog":
return Dog(name)
elif animal_type == "cat":
return Cat(name)
else:
raise ValueError(f"Unknown animal type: {animal_type}")
Usage¶
# Create factory
factory = AnimalFactory()
# Create different animals using the factory
dog = factory.get_animal("dog", "Buddy")
cat = factory.get_animal("cat", "Whiskers")
print(dog.speak()) # Output: Buddy says woof!
print(cat.speak()) # Output: Whiskers says meow!
Trade-offs¶
Benefits:
- Encapsulation of object creation logic, hidden from clients
- Easy to add new product types without modifying client code
- Loose coupling through dependency on interfaces rather than concrete classes
- Single Responsibility Principle by separating creation from business logic
Drawbacks:
- Increased complexity through additional classes and indirection
- Factory can become large with many product types
- Changing the factory interface affects all clients
- Limited flexibility as simple factories create only one type at a time
Real-World Examples¶
- Database connections based on configuration
- Document parsers based on file type
- Platform-specific UI elements
- Logger implementations (file, console, remote)
Related Patterns¶
- Abstract Factory
- Builder
- Prototype
- Singleton
API Reference¶
design_patterns.creational.factory
¶
This module demonstrates the Factory design pattern, which is a creational pattern used to create objects without specifying the exact class of object that will be created. The Factory pattern defines an interface for creating an object, but allows subclasses to alter the type of objects that will be created. In this implementation, the AnimalFactory class creates instances of Dog or Cat based on the input type.
AnimalFactory
¶
Factory class to create Animal instances.
Usage
Source code in src/design_patterns/creational/factory.py
get_animal(animal_type, name)
¶
Creates an instance of Animal based on the provided type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
animal_type
|
str
|
The type of animal to create ('dog' or 'cat'). |
required |
name
|
str
|
The name of the animal. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Animal |
Animal
|
An instance of Dog or Cat. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the animal_type is not 'dog' or 'cat'. |