← Back to list

Factory Method: Decoupling Object Creation the Right Way

Intent

Syed Hassan Hashmi · 2026-02-26 03:05 · 0 claps · 3.5 min read
#design-patterns #factory-method-pattern #software-design #software-architecture
Open on Medium ↗
Wiki topics: 🏛️ · Architecture

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 Transport interface.
  • 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

  1. The client code works with the abstract Logistics class.
  2. At runtime, it decides which concrete subclass to instantiate.
  3. The subclass decides which Transport to create.
  4. 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

  1. Identify the common interface (Transport).
  2. Create concrete implementations (Truck, Ship).
  3. Declare a factory method in a base class.
  4. Replace direct constructor calls with the factory method.
  5. 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