Factory Pattern in Java: Simple Guide with Real Examples (2026)

Factory Pattern in Java: Simple Guide with Real Examples (2026)

Factory Pattern in Java: Simple Guide with Real Examples

Factory Pattern is the second design pattern most people learn after Singleton. It sounds complicated, but the idea is very simple — instead of creating objects yourself, you ask a "factory" to create them for you. In this guide, I will explain it in plain words, show you a real payment system example, and walk through all three types you will see in real projects.

What is Factory Pattern, in simple words?

Imagine you are writing code for an online shop. Customers can pay using credit card, UPI, PayPal, or net banking. Each type of payment needs different code to process.

So you might write something like this:

if (type.equals("credit")) {
    return new CreditCardPayment();
} else if (type.equals("upi")) {
    return new UpiPayment();
} else if (type.equals("paypal")) {
    return new PayPalPayment();
} else if (type.equals("netbanking")) {
    return new NetBankingPayment();
}

This works. But there are problems.

  • Every time you add a new payment method, you have to find every place with this code and change it
  • The creation logic is scattered all over the codebase
  • Testing is hard because your code directly depends on specific classes

Factory Pattern fixes this. Instead of deciding which class to create yourself, you hand that decision to a factory class. Your main code just says: "Give me a payment method for UPI." The factory figures out the details.

That is the whole idea. Do not create objects yourself. Ask a factory to do it.

Simple, right? Now let's see how it actually looks in code.

A real-life example: ordering pizza

Before we dive into Java code, let me give you a picture that will make everything click.

Imagine you are at a pizza shop.

You walk up to the counter and say: "One margherita pizza, please."

You do not:

  • Roll the dough yourself
  • Chop the tomatoes
  • Spread the cheese
  • Put it in the oven
  • Box it up

You just say what you want. The kitchen — the factory — does all the work and hands you the pizza.

The kitchen also hides the mess. You do not know which oven was used, who made the dough, or what brand of cheese was used. You just want pizza. And you get pizza.

That is the Factory Pattern in one picture. You ask for what you want. The factory handles the details.

And if tomorrow the pizza shop adds a new "paneer pizza" to the menu? You do not need to learn anything new. You just ask for it. The kitchen handles the changes.

Type 1: Simple Factory (the easy one)

This is the easiest version of Factory Pattern. It is not technically one of the "official" 23 patterns from the Gang of Four book. But it is so widely used that most developers treat it as a pattern.

Let me show you how it works with our payment example.

Step 1: Create a common interface

public interface Payment {
    void pay(double amount);
}

This just says: "Any payment method must be able to pay()." It does not say how.

Step 2: Create concrete classes

public class CreditCardPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using Credit Card");
    }
}

public class UpiPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using UPI");
    }
}

public class PayPalPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using PayPal");
    }
}

Each class handles one payment method. Each one knows how to process its own kind of payment.

Step 3: Create the factory

public class PaymentFactory {
    public static Payment createPayment(String type) {
        if (type == null) return null;

        switch (type.toLowerCase()) {
            case "credit": return new CreditCardPayment();
            case "upi": return new UpiPayment();
            case "paypal": return new PayPalPayment();
            default: throw new IllegalArgumentException("Unknown payment type: " + type);
        }
    }
}

This is the factory. It has one job: given a type, return the right object.

Step 4: Use it in your code

public class Shop {
    public static void main(String[] args) {
        Payment payment = PaymentFactory.createPayment("upi");
        payment.pay(500);

        Payment payment2 = PaymentFactory.createPayment("credit");
        payment2.pay(1200);
    }
}

Look at the Shop class. It does not know anything about CreditCardPayment, UpiPayment, or any other specific class. It just asks the factory: "Give me a payment method for UPI." The factory does the rest.

Why this is better

  • If you add a new payment type tomorrow, you only change the factory
  • Your business code stays clean and focused on real work
  • Testing is easier because you can swap the factory for a fake one

The one limitation

If you add a new type — say, crypto payments — you have to modify the factory. The factory knows about every payment class. That is fine for small projects. But in big systems with dozens of types, it becomes a maintenance problem.

That is where the next two types come in.

Type 2: Factory Method (the flexible one)

Factory Method solves the limitation of Simple Factory. Instead of one factory knowing every type, you create a different factory for each type.

Yes, it sounds like more work. But it means the code is more flexible. Let me show you.

The idea

You have a base "creator" class. It has a method called createPayment(). But the method does not create anything itself — it just declares that a payment will be created. Subclasses fill in the details.

public abstract class PaymentCreator {
    // This is the factory method
    public abstract Payment createPayment();

    // Common logic used by all creators
    public void processPayment(double amount) {
        Payment payment = createPayment();
        payment.pay(amount);
        System.out.println("Payment processing done.");
    }
}

Now create subclasses, one for each type:

public class CreditCardCreator extends PaymentCreator {
    @Override
    public Payment createPayment() {
        return new CreditCardPayment();
    }
}

public class UpiCreator extends PaymentCreator {
    @Override
    public Payment createPayment() {
        return new UpiPayment();
    }
}

public class PayPalCreator extends PaymentCreator {
    @Override
    public Payment createPayment() {
        return new PayPalPayment();
    }
}

Using it

public class Shop {
    public static void main(String[] args) {
        PaymentCreator creator = new UpiCreator();
        creator.processPayment(500);

        PaymentCreator creator2 = new CreditCardCreator();
        creator2.processPayment(1200);
    }
}

Why this is better than Simple Factory

  • Each creator knows only about its own payment type. No giant switch statement.
  • Adding a new type means adding a new creator class. You do not touch existing code.
  • The base creator class can hold common logic (like logging, validation) that every type shares.

The trade-off

You end up with more classes. Three payment types means three creators plus three payments = six classes. Simple Factory did it in four. The extra classes buy you flexibility.

In small projects, this is overkill. In big projects, it is worth it.

Type 3: Abstract Factory (the enterprise one)

Abstract Factory is the most complex of the three. It is used when you need to create families of related objects — objects that are meant to work together.

The classic example is UI themes.

The idea

Imagine you are building an app that supports both light mode and dark mode. In light mode, you need light buttons, light checkboxes, light text boxes. In dark mode, dark versions of all those.

You do not want to accidentally create a dark button and a light checkbox in the same screen. It would look terrible.

Abstract Factory solves this by giving you a factory that creates an entire family at once.

Step 1: Create interfaces for each product

public interface Button {
    void paint();
}

public interface Checkbox {
    void paint();
}

Step 2: Create light and dark versions

public class LightButton implements Button {
    public void paint() { System.out.println("Rendering Light Button"); }
}

public class DarkButton implements Button {
    public void paint() { System.out.println("Rendering Dark Button"); }
}

public class LightCheckbox implements Checkbox {
    public void paint() { System.out.println("Rendering Light Checkbox"); }
}

public class DarkCheckbox implements Checkbox {
    public void paint() { System.out.println("Rendering Dark Checkbox"); }
}

Step 3: Create the abstract factory

public interface UIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

Step 4: Create one factory for each theme

public class LightThemeFactory implements UIFactory {
    public Button createButton() { return new LightButton(); }
    public Checkbox createCheckbox() { return new LightCheckbox(); }
}

public class DarkThemeFactory implements UIFactory {
    public Button createButton() { return new DarkButton(); }
    public Checkbox createCheckbox() { return new DarkCheckbox(); }
}

Step 5: Use it

public class App {
    public static void main(String[] args) {
        UIFactory factory = new DarkThemeFactory();

        Button button = factory.createButton();
        Checkbox checkbox = factory.createCheckbox();

        button.paint();      // Rendering Dark Button
        checkbox.paint();    // Rendering Dark Checkbox
    }
}

Now you can never accidentally mix a light button with a dark checkbox. The factory guarantees consistency.

When to use this

Abstract Factory is overkill for most projects. It is useful when:

  • You have multiple "families" of related objects
  • Objects from one family must be used together
  • You want to switch entire families easily at runtime

Cross-platform UI frameworks, database drivers, and cloud provider SDKs are common real uses.

Which one should you use?

Here is a simple comparison to help you choose.

Type When to use Complexity
Simple Factory Small projects. You have a few types and want a clean way to create them. Very low
Factory Method Medium projects. You want each creator to be independent and testable. Medium
Abstract Factory Large projects. You need families of related objects that must stay consistent. High

My honest advice for beginners: start with Simple Factory. It is 90% of what you will need in day-to-day work. Learn Factory Method and Abstract Factory later, when you actually face a problem they solve.

You do not need to write Abstract Factory on day one. Do not let anyone tell you otherwise.

When to use Factory Pattern (and when not to)

Good times to use Factory Pattern

  • You have multiple classes that do the same kind of thing (payment methods, database drivers, file parsers)
  • The exact class to create is decided at runtime, not at compile time
  • Creating the object involves setup — configuration, connections, reading files
  • You want to keep object creation in one place so it is easy to change
  • You want to write unit tests where you swap real classes for fake ones

Bad times to use Factory Pattern

  • You only have one class. Just use new directly.
  • The class to create never changes. A factory adds nothing here.
  • You are adding a factory "just in case" for the future. That is over-engineering.
  • The factory would just be a wrapper around a single new call. That is not a factory — that is a detour.

The rule I use: if you have three or more similar classes and you find yourself writing a switch statement to pick between them, use a factory.

Otherwise, plain new is fine.

Where you will see it in real Java code

Factory Pattern is everywhere in Java. You have probably used it today without knowing.

  • Calendar.getInstance() — returns a Calendar object without you knowing which subclass
  • NumberFormat.getInstance() — returns a formatter based on your locale
  • DocumentBuilderFactory.newInstance() — creates the right XML parser
  • Executors.newFixedThreadPool(5) — creates a thread pool without you configuring the internals
  • Spring BeanFactory — creates and manages all your Spring beans
  • JDBC DriverManager.getConnection() — creates a connection without you knowing which database driver is behind it
  • Log4j LoggerFactory.getLogger() — creates a logger for your class

See the pattern? Every one of these hides the messy details of object creation. You just say what you want, and the factory gives it to you.

Common questions

What is Factory Pattern in simple words?

Factory Pattern is a design pattern where you do not create objects directly with the new keyword. Instead, you ask a factory class to create the object for you. The factory decides which class to instantiate, so your code stays clean.

Why do we need Factory Pattern in Java?

Factory Pattern keeps the object creation logic in one place. If tomorrow you add a new class, you only change the factory, not every place in your code. It also makes your code easier to test and maintain.

What are the 3 types of Factory Pattern?

There are three common types: Simple Factory (one class with a switch), Factory Method (subclasses decide which object to create), and Abstract Factory (creates families of related objects). Simple Factory is easiest to learn.

What is the difference between Factory Method and Abstract Factory?

Factory Method creates one type of object using subclasses. Abstract Factory creates a family of related objects using one factory class. If you only need one product, use Factory Method. If you need multiple products that go together, use Abstract Factory.

Is Simple Factory a real design pattern?

Strictly speaking, no. Simple Factory is not in the original Gang of Four book. But it is so widely used that most developers treat it as a pattern. It is the easiest starting point for beginners.

When should I use Factory Pattern?

Use it when the exact class to create is not known at compile time, when creating an object is complex, or when you want to keep object creation in one place. Do not use it for simple cases where new keyword works fine.

Where to go next

You now understand Factory Pattern better than most working developers. You know the three types, when to use each one, and you have seen a real payment system example that you can adapt to your own projects.

If you remember one thing, remember this: Factory Pattern is about saying "give me X" instead of saying "create X in this specific way." It hides the messy details behind a clean, simple interface.

But do not overuse it. If you only have one class, just use new. Factories earn their place when you have many similar classes and want to keep them organized.

If this helped, bookmark it. But the real learning happens when you open your IDE and type the code yourself. Write a small factory for something you use every day — a logger, a file reader, a URL fetcher. It will stick faster than any tutorial.

No comments: