DEV Community

Heli Shah
Heli Shah

Posted on

1 1 1 1 1

Understanding Factory Design Pattern: A Simple Guide

"The name Factory itself suggests that it will create something for us."
That's exactly what it does—the Factory Method generates objects for us so that we don't have to instantiate them directly.

What is the Factory Design Pattern?

The Factory Pattern is a type of creational design pattern. As the name implies, it’s all about creating objects—but in a way that adds flexibility, scalability, and maintainability to your codebase.

Instead of writing code that instantiates classes directly using new, you delegate that responsibility to a factory method. This method encapsulates the logic of choosing which object to create and returns it, hiding the instantiation details from the client.

Why Should You Use the Factory Pattern?

Let’s consider a real-world analogy. When you go to a car showroom, you don’t build your car—you tell the representative what kind of car you want, and they bring it to you. You use the car; you don’t care how it was built.

The Factory pattern works the same way:

You request an object.

The factory creates it and gives it to you.

You use it without worrying about how it was made.

Benefits:

  • Decouples object creation from its usage.
  • Supports polymorphism, enabling easy extension.
  • Makes your code open for extension but closed for modification.
  • Centralizes creation logic, making maintenance easier.

Structure of the Factory Pattern:

At a high level, here’s how the Factory pattern is structured:

  • Product Interface/Abstract Class – common interface for all products.
  • Concrete Products – specific implementations.
  • Creator/Factory Class – contains the factory method that returns a product.

Real-World Example: Ride Sharing App (Uber, Lyft):

Imagine you're building a ride-sharing app like Uber or Lyft. Users can choose different types of rides: Standard, Luxury, or SUV.

Rather than having the app directly instantiate each ride type using new StandardRide(), new LuxuryRide(), etc., we use a RideFactory to handle that logic.

Problem
You want to avoid hardcoding logic like:

if (rideType.equals("standard")) {
    ride = new StandardRide();
}
Enter fullscreen mode Exit fullscreen mode

throughout the app. Instead, centralize and abstract it using a Factory.

Applying the Factory Pattern

Step 1: Common Interface

public interface Ride {
    void bookRide();
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Concrete Ride Types

public class StandardRide implements Ride {
    public void bookRide() {
        System.out.println("Standard ride booked. Arriving in 5 minutes.");
    }
}

public class LuxuryRide implements Ride {
    public void bookRide() {
        System.out.println("Luxury ride booked. A premium car is on its way.");
    }
}

public class SUVRide implements Ride {
    public void bookRide() {
        System.out.println("SUV ride booked. Perfect for group travel.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: The Factory Class

public class RideFactory {

    public Ride getRide(String rideType) {
        if (rideType == null) return null;

        switch (rideType.toLowerCase()) {
            case "standard":
                return new StandardRide();
            case "luxury":
                return new LuxuryRide();
            case "suv":
                return new SUVRide();
            default:
                throw new IllegalArgumentException("Unknown ride type");
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

Step 4: Client Code

public class Main {
    public static void main(String[] args) {
        RideFactory factory = new RideFactory();

        Ride ride1 = factory.getRide("luxury");
        ride1.bookRide();  // Luxury ride booked...

        Ride ride2 = factory.getRide("suv");
        ride2.bookRide();  // SUV ride booked...
    }
}
Enter fullscreen mode Exit fullscreen mode

When Should You Use It?

  • When your code needs to create multiple types of objects that share a common interface.
  • When you want to isolate object creation logic from business logic.
  • When the creation process is complex or might change in the future.

When Not to Use It?

  • If you only have one class and object creation is straightforward, a factory may be overkill.
  • In performance-critical code paths, extra abstraction might add unnecessary overhead.

Wrapping Up:

The Factory Design Pattern is a powerful tool in your OOP toolkit. It simplifies object creation and helps you write cleaner, more modular, and more maintainable code. Like any design pattern, the key is knowing when to use it.

Next time you’re faced with multiple object types and a need for flexible instantiation, remember:

“Don’t call the constructor—let the factory handle it.”

Top comments (0)