As code grows, object creation often becomes more complex than it first appears. Questions like “when should this be created?”, “which implementation should be used?”, and “what setup is required?” can spread across the codebase. The factory pattern is one of the classic ways to manage that creation responsibility.
In this post, we will cover:
- what the factory pattern is
- why creation responsibility should sometimes be separated
- when it fits well
- how it connects to strategy and DIP
The key idea is that the factory pattern reduces coupling by keeping object-using code from knowing too much about object creation details.
What is the factory pattern?
A very simple phrasing is:
- instead of constructing objects directly with
new - delegate creation to a dedicated place
The caller expresses what it needs, while the factory handles the concrete creation details.
Why separate creation responsibility?
If code creates objects directly everywhere:
- concrete class knowledge spreads
- creation conditions grow into branches
- initialization rules get duplicated
A factory centralizes those rules and makes them easier to manage.
When does it fit well?
- when creation conditions are complex
- when implementations vary by environment
- when initialization has several steps
- when callers should know less about concrete types
So it becomes useful when object creation is itself a meaningful design concern.
How is it different from the strategy pattern?
The two often appear together, but they solve different problems.
- strategy pattern: behavior substitution
- factory pattern: creation responsibility separation
A factory may even create strategy objects.
How does it connect to DIP?
Factories can keep concrete implementation decisions concentrated in one place, allowing the rest of the code to depend more on abstractions.
That means:
- usage code can know only the abstract role
- while the factory decides which concrete implementation to create
Common misunderstandings
1. You should always avoid new, so factories are always required
Not at all. If creation is simple, a factory may be unnecessary.
2. The factory pattern only increases class count
It can in small cases, but once creation logic becomes complex it often improves clarity a lot.
3. Frameworks make factory thinking irrelevant
Frameworks can help, but deciding where creation responsibility belongs is still a design question.
Simple Example
interface PaymentStrategy {
pay(amount: number): void;
}
class CardPayment implements PaymentStrategy {
pay(amount: number) {
console.log(`Card: ${amount}`);
}
}
class PointsPayment implements PaymentStrategy {
pay(amount: number) {
console.log(`Points: ${amount}`);
}
}
class PaymentFactory {
static create(method: 'card' | 'points'): PaymentStrategy {
if (method === 'card') return new CardPayment();
return new PointsPayment();
}
}
const strategy = PaymentFactory.create('card');
strategy.pay(100);
The key point is that the creation rule stays inside PaymentFactory, so callers know less about concrete class details.
FAQ
Q. Where should beginners try factories first?
Start where different implementations are selected under different conditions.
Q. Is factory the same as DI?
No, but they are related because both deal with creation and dependency wiring.
Q. Is a factory needed for simple creation?
Not always. It becomes more valuable when creation logic carries real complexity or variability.
Read Next
- For behavior structure, continue with the Strategy Pattern Guide.
- For dependency wiring, read the Dependency Injection Guide.
While AdSense review is pending, related guides are shown instead of ads.
Start Here
Continue with the core guides that pull steady search traffic.
- Middleware Troubleshooting Guide: Redis vs RabbitMQ vs Kafka A practical middleware troubleshooting guide for developers covering when to reach for Redis, RabbitMQ, or Kafka symptoms first, and which problem patterns usually belong to each tool.
- Kubernetes CrashLoopBackOff: What to Check First A practical Kubernetes CrashLoopBackOff troubleshooting guide covering startup failures, probe issues, config mistakes, and what to inspect first.
- Kafka Consumer Lag Increasing: Troubleshooting Guide A practical Kafka consumer lag troubleshooting guide covering what lag usually means, which consumer metrics to check first, and how poll timing, processing speed, and fetch patterns affect lag.
- Kafka Rebalancing Too Often: Common Causes and Fixes A practical Kafka troubleshooting guide covering why consumer groups rebalance too often, what poll timing and group protocol settings matter, and how to stop rebalances from interrupting useful work.
- Docker Container Keeps Restarting: What to Check First A practical Docker restart-loop troubleshooting guide covering exit codes, command failures, environment mistakes, health checks, and what to inspect first.
While AdSense review is pending, related guides are shown instead of ads.