Factory Method: Decoupling Object Creation the Right Way
Intent
Factory Method: Decoupling Object Creation the Right Way

Intent
Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
Instead of instantiating objects directly using new, The creation logic is delegated to subclasses through a special method - the factory method.
In simple words:
It moves object creation out of the client code and into a dedicated method that subclasses can override.
Problem
Imagine you’re building a logistics application.
At first, your system only supports road transport, so your core business logic directly instantiates Truck objects.
Truck truck = new Truck();
truck.deliver();
Everything works.
But soon, the business expands. Now you must support:
- Sea transport (
Ship) - Rail transport (
Train) - Air transport (
Airplane)
You modify the code:
if (mode.equals("road")) {
transport = new Truck();
} else if (mode.equals("sea")) {
transport = new Ship();
} else if (mode.equals("rail")) {
transport = new Train();
}
Now problems begin:
- Your core business logic depends on concrete classes
- Every new transport type requires modifying existing logic
- The code violates the Open/Closed Principle
- Testing becomes harder because object creation is tightly coupled
- Conditionals start spreading across the codebase
This is how systems slowly become rigid and hard to maintain.
The real issue is not transport types.
The real issue is that object creation is mixed with business logic.
Solution
The Factory Method pattern suggests:
Replace direct object construction calls with calls to a special factory method.
Instead of:
new Truck();
new Ship();
You introduce an abstract method:
createTransport()
The base class defines the method, but subclasses decide which concrete transport to instantiate.
This way:
- The core logic works with the
Transportinterface. - The decision of which transport to create is delegated.
- New transport types can be introduced without changing existing client logic.
The key principle:
Depend on abstractions, not concrete implementations.
Structure
The Factory Method pattern consists of four main participants:
1. Product
Defines the interface of objects that the factory method creates.
interface Transport {
void deliver();
}
2. Concrete Products
Different implementations of the Transport interface.
class Truck implements Transport {
public void deliver() {
System.out.println("Delivering cargo by road.");
}
}
class Ship implements Transport {
public void deliver() {
System.out.println("Delivering cargo by sea.");
}
}
Each product provides its own implementation of delivery.
3. Creator
Declares the factory method.
abstract class Logistics {
// Factory Method
abstract Transport createTransport();
public void planDelivery() {
Transport transport = createTransport();
transport.deliver();
}
}
Notice something important:
planDelivery() depends only on Transport, not on Truck or Ship.
This is the decoupling point.
4. Concrete Creators
Override the factory method to return specific products.
class RoadLogistics extends Logistics {
@Override
Transport createTransport() {
return new Truck();
}
}
class SeaLogistics extends Logistics {
@Override
Transport createTransport() {
return new Ship();
}
}
Now the responsibility of choosing the transport type is delegated to subclasses.
How It Works
- The client code works with the abstract
Logisticsclass. - At runtime, it decides which concrete subclass to instantiate.
- The subclass decides which
Transportto create. - The business logic remains unchanged.
Example usage:
Logistics logistics = new RoadLogistics();
logistics.planDelivery();
Or:
Logistics logistics = new SeaLogistics();
logistics.planDelivery();
The client never touches new Truck() or new Ship() directly.
That’s the power of the pattern.
Applicability
Use Factory Method when:
1. You Don’t Know in Advance Which Class You’ll Need
If transport type depends on configuration, user input, or environment, Factory Method provides flexibility.
2. You Want to Follow Open/Closed Principle
New transport types (e.g., AirLogistics) can be added without modifying existing classes.
3. You’re Building Extensible Systems
Frameworks often use Factory Method so developers can extend behavior without changing the core.
4. You Want to Isolate Object Creation Logic
This makes testing easier and improves the separation of concerns.
How to Implement
- Identify the common interface (
Transport). - Create concrete implementations (
Truck,Ship). - Declare a factory method in a base class.
- Replace direct constructor calls with the factory method.
- Create subclasses that override the factory method.
Important advice:
- Keep the factory method small.
- Avoid adding conditional logic inside the factory — that defeats the purpose.
- Let inheritance handle variation.
Pros and Cons
Pros
- Eliminates tight coupling between the creator and concrete products.
- Supports the Open/Closed Principle.
- Improves testability.
- Makes code more modular.
- Centralizes object creation
Cons
- Can introduce many subclasses.
- Slightly increases structural complexity.
- Overkill for very simple cases
In real-world enterprise systems, the benefits usually outweigh the added structure.
Relations with Other Patterns
Factory Method vs Abstract Factory
Factory Method creates one product. Abstract Factory creates families of related products.
Factory Method and Template Method
The factory method is often part of a template method where object creation is one step of a larger algorithm.
Factory Method and Dependency Injection
Modern frameworks sometimes replace classical Factory Method usage with dependency injection containers — but conceptually, they solve the same decoupling problem.
Final Thoughts
Factory Method is not about avoiding new.
It’s about controlling change.
When your application grows and transport types evolve, the pattern ensures that:
- You extend behavior without breaking existing code.
- You isolate variation.
- Your architecture remains stable.
Used correctly, it keeps systems flexible.
Used unnecessarily, it adds complexity.
Like all patterns — it’s a tool, not a rule.
메타데이터
- post_id
- 3d2da4f20cbc
- slug
- factory-method-decoupling-object-creation-the-right-way-3d2da4f20cbc
- url
- https://medium.com/@syedh9837/factory-method-decoupling-object-creation-the-right-way-3d2da4f20cbc
- canonical_url
- https://medium.com/@syedh9837/factory-method-decoupling-object-creation-the-right-way-3d2da4f20cbc
- author_url
- https://medium.com/@syedh9837
- status
- ok
- fetched_at
- 2026-06-24 18:57:25