DEV Community

Cover image for Design Patterns Simplified: Part 1 – Factory Pattern and Its Clones (Simple, Method, Abstract)
Prateek Prabhakar
Prateek Prabhakar

Posted on • Edited on • Originally published at Medium

Design Patterns Simplified: Part 1 – Factory Pattern and Its Clones (Simple, Method, Abstract)

Factory Pattern belongs to the Creational family of design patterns.
Why? Because it's all about how objects are created, and how to make that process cleaner, scalable, and easier to manage.
Think of it as the Zomato of object creation. You just pick what you want — it gets delivered, no messy kitchen involved.

WHY would you use it?

When you’re just starting out, things look innocent,

if type == "Email"
    return new EmailSender()
else if type == "SMS"
    return new SmsSender()
Enter fullscreen mode Exit fullscreen mode

And it works! Until, you need to support 8 more types, copy this block across 6 services, and one tiny change breaks 4 things at once.

This is the tipping point where Factory Patterns saves the day.
Centralize object creation
Makes the codebase cleaner and easier to test
Follows the Open-Closed Principle
Be confident that the changes won’t break everything

WHEN would you use it?

You’re creating objects based on dynamic input (type, config, user input, etc.)
You want to remove if-else based object creation logic from business code
You anticipate new types being added over time
You want to test or swap creation logic without touching main workflows

Now, just when you might have started feeling comfortable with the WHY and the WHEN, let me break it to you! Its not just one, but 3 different variety of Factory patterns that exist. Another headache to choose the best one.
Don't panic, I will help you have a clear distinction between these, so that you apply the correct one at the correct place.

  • Simple Factory – great for small messes and big headaches caused by if-else jungles

  • Factory Method – ideal when object creation varies per type

  • Abstract Factory – perfect when you're producing families of related objects

Let's dive into each one ahead.


1. Simple Factory (a.k.a. “Not Even a Real Pattern”)

What it is?
A class with one method that returns the object you want based on input.

Why you’d use it?
You want to clean up repetitive if-else or switch blocks scattered all over your codebase.

What does the code looks like?

Class NotificationFactory
    Static Method GetSender(type)
        if type == "email"
            return new EmailSender()
        else if type == "sms"
            return new SmsSender()
Enter fullscreen mode Exit fullscreen mode
// Caller logic
// Step 1: Choose the type dynamically (from config, UI, etc.)
notificationType = GetUserPreference()  // returns "email" or "sms"

// Step 2: Ask the factory to create the sender
sender = NotificationFactory.GetSender(notificationType)

// Step 3: Use the sender, no idea what the real class is
sender.Send("Simple Factory is… simply awesome!")
Enter fullscreen mode Exit fullscreen mode

Use Cases?

  • Notification systems
  • Payment providers (Stripe, Razorpay, PayPal, etc.)
  • Report generators

When to use?

  • You have a few object types
  • Changes are rare
  • You're tired of if-else déjà vu

Limitations?
Every time you add a new type, you have to edit the factory, breaking the Open-Closed Principle. It's like fixing one leak and causing two more.

2. Factory Method Pattern (The Upgrade)

What it is?
Let the subclasses handle object creation, so your main code stays neat, extensible, and future-proof. No more if-else. Your code grows with new classes, not new conditions.

Why you’d use it?
You want to scale by hiring new types of “creators”, each with their own logic, and you don’t want one massive switch case that gets worse every week. Each creator is like a company's Vertical Head — they hire their own team (senders), and the CEO (caller code) doesn’t need to micromanage hiring logic.

What does the code looks like?

Abstract Class NotificationCreator
    Abstract Method CreateSender()

Class EmailCreator extends NotificationCreator
    Method CreateSender() → new EmailSender()

Class SmsCreator extends NotificationCreator
    Method CreateSender() → new SmsSender()
Enter fullscreen mode Exit fullscreen mode
// Caller logic
// Step 1: Choose the correct creator
creator = new EmailCreator()  // or new SmsCreator()

// Step 2: Use the Factory Method to get the sender
sender = creator.CreateSender()

// Step 3: Use the sender (which could be EmailSender, SmsSender, etc.)
sender.Send("Hello from the Factory Method!")
Enter fullscreen mode Exit fullscreen mode

Use Cases?

  • Multi-channel message dispatchers(Email, SMS, Slack, etc.)
  • When multiple teams own separate creation logic

When to use?

  • You want to follow SOLID principles (especially Open-Closed)
  • New object types are added regularly
  • Each creator class is testable on its own (makes code less error prone)

3. Abstract Factory Pattern (The Big Boss)

What it is?
A factory that returns a family of related objects.
Imagine you're building a website that supports Dark and Light theme modes. You don’t want just a button. You want a button, input, and dropdown that all match the respective theme (i.e. a Family). All the UI components must vibe together, like a good outfit. No DarkButton wearing LightInput jeans.

Why you’d use it?
You're dealing with systems that create grouped components. All or nothing.

What does the code looks like?

Interface ThemeFactory
    Method CreateButton()
    Method CreateInput()

Class LightThemeFactory
    Method CreateButton() → LightButton
    Method CreateInput() → LightInput

Class DarkThemeFactory
    Method CreateButton() → DarkButton
    Method CreateInput() → DarkInput
Enter fullscreen mode Exit fullscreen mode
// Caller logic: decides theme
theme = GetUserSelectedTheme() // "light" or "dark"

// Step 1: Choose the appropriate concrete factory
If theme == "light"
    factory = new LightThemeFactory()
Else
    factory = new DarkThemeFactory()

// Step 2: Use the abstract factory interface
button = factory.CreateButton()
input = factory.CreateInput()

// Step 3: Use the created objects (polymorphically)
button.Render()
input.Render()
Enter fullscreen mode Exit fullscreen mode

Use Cases?

  • UI component kits (Light Theme vs Dark Theme)
  • Cross-platform libraries (Mac vs Windows behaviour)

When to use?

  • You need related objects created together
  • You want consistency (example, no mix of LightButton with DarkInput)
  • You want to switch entire object families easily

To summarize, it would be apt to say,

Factory pattern is a design pattern that hides the object creation logic behind a common interface, so your code can focus on “what” to make, not “how” it’s made.

Scenario Pattern
Just cleaning up a few repeated object creations? Simple Factory
Want to add new object types without touching existing code? Factory Method
Need to create grouped objects that belong together? Abstract Factory

Hope you liked the post, and would be confident enough to speak about the Factory design pattern.

Next up in the series, lets dive into the Strategy Pattern.

Top comments (0)