After Dependency Injection, a natural question appears in real systems:
If classes don’t create objects, and dependencies are injected externally, who is responsible for creating them?
This is where Factories come in.
The Problem: Object Creation Becomes Complex
At first, object creation looks simple:
payment = CardPayment()
But in real systems, creation logic becomes complex:
- multiple implementations exist
- selection depends on input or configuration
- dependencies also need to be constructed
If this logic is scattered everywhere, the system becomes inconsistent.
Bad Design: Creation Inside Business Logic
class PaymentService:
def process(self, type):
if type == "card":
payment = CardPayment()
elif type == "upi":
payment = UpiPayment()
What’s wrong here?
- creation logic is mixed with business logic
- violates Open-Closed Principle
- adding new types requires modifying existing code
- duplication across services is likely
What is a Factory?
A factory is responsible for:
Centralizing and controlling object creation logic.
It hides complexity and returns ready-to-use objects.
Simple Factory Example
class PaymentFactory:
def create(self, type):
if type == "card":
return CardPayment()
elif type == "upi":
return UpiPayment()
Usage
payment = PaymentFactory().create("card")
payment.pay()
What Changed?
- object creation is centralized
- business logic is clean
- new implementations can be added in one place
Why Factories Matter
1. Centralized Creation Logic
All object creation rules live in one place.
2. Better Maintainability
Changes do not spread across the system.
3. Controlled Instantiation
Ensures correct object construction.
Factory vs Dependency Injection
These are often confused, but they solve different problems:
| Dependency Injection | Factory |
|---|---|
| provides objects | creates objects |
| focuses on usage | focuses on creation |
| reduces coupling | centralizes instantiation |
Real System Example
Notification System
class NotificationFactory:
def create(self, type):
if type == "email":
return EmailNotifier()
elif type == "sms":
return SmsNotifier()
Now services don’t care how objects are created:
notifier = factory.create("email")
notifier.send("Hello")
Key Design Insight
Factories control object creation, ensuring consistency and isolating construction logic from business logic.
When to Use Factories
Use factories when:
- multiple implementations exist
- object creation involves logic or conditions
- construction is complex or dependent on configuration
When NOT to Use Factories
Avoid factories when:
- object creation is trivial
- no variation exists
- abstraction adds unnecessary complexity
Common Mistake
Beginners often:
- put business logic inside factories
- overuse factories for simple objects
- confuse factory with dependency injection
Factories should only handle creation, nothing else.
Design Principle
Separate object creation from object usage to maintain clean and scalable architecture.
One-Line Takeaway
Factories centralize object creation logic, keeping business code clean and focused on behavior.
Top comments (0)