Abstract Factory Design Pattern



This content originally appeared on DEV Community and was authored by Priyank Bhardwaj

☕ Introduction

Design patterns are like battle-tested solutions to common problems in software design. One such pattern is the Abstract Factory Pattern, which falls under Creational Design Patterns. In this article, we’ll break it down with a real-world analogy, implement it in Java, and explain each step thoroughly.

🧠 What is the Abstract Factory Pattern?

The Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Think of it as a super-factory, also known as a factory of factories.

🎯 When to Use?

  • When your code needs to work with various families of related products.
  • When you want to enforce consistency among objects.
  • When you want to hide the creation logic from the client code.

🏠 Real-Life Analogy

Imagine a Furniture Store

You sell Modern and Victorian styles of furniture. Each style has:

  • A Chair
  • A Sofa

You don’t want customers (client code) to create ModernChair or VictorianSofa directly. Instead, you give them a FurnitureFactory, which gives them appropriate combinations of products.

🧱 Class Diagram Overview

                  +---------------------+
                  |   FurnitureFactory  |<-- Abstract Factory
                  +---------------------+
                  | + createChair()     |
                  | + createSofa()      |
                  +---------------------+
                      /          \
                     /            \
+------------------------+    +---------------------------+
| ModernFurnitureFactory |    | VictorianFurnitureFactory |
+------------------------+    +---------------------------+
| + createChair()        |    | + createChair()           |
| + createSofa()         |    | + createSofa()            |
+------------------------+    +---------------------------+

        ^                                  ^
        |                                  |
+---------------+                 +-----------------+
|   ModernChair |                 | VictorianChair  |
+---------------+                 +-----------------+

+---------------+                 +-----------------+
|   ModernSofa  |                 | VictorianSofa   |
+---------------+                 +-----------------+

🧑‍💻 Let’s Implement It in Java

Step 1: Abstract Product Interfaces


// Chair.java
public interface Chair {
    void sitOn();
}

// Sofa.java
public interface Sofa {
    void lieOn();
}

Step 2: Concrete Products


// ModernChair.java
public class ModernChair implements Chair {
    public void sitOn() {
        System.out.println("Sitting on a modern chair.");
    }
}

// VictorianChair.java
public class VictorianChair implements Chair {
    public void sitOn() {
        System.out.println("Sitting on a Victorian chair.");
    }
}

// ModernSofa.java
public class ModernSofa implements Sofa {
    public void lieOn() {
        System.out.println("Lying on a modern sofa.");
    }
}

// VictorianSofa.java
public class VictorianSofa implements Sofa {
    public void lieOn() {
        System.out.println("Lying on a Victorian sofa.");
    }
}

Step 3: Abstract Factory


// FurnitureFactory.java
public interface FurnitureFactory {
    Chair createChair();
    Sofa createSofa();
}

Step 4: Concrete Factories


// ModernFurnitureFactory.java
public class ModernFurnitureFactory implements FurnitureFactory {
    public Chair createChair() {
        return new ModernChair();
    }
    public Sofa createSofa() {
        return new ModernSofa();
    }
}

// VictorianFurnitureFactory.java
public class VictorianFurnitureFactory implements FurnitureFactory {
    public Chair createChair() {
        return new VictorianChair();
    }
    public Sofa createSofa() {
        return new VictorianSofa();
    }
}

Step 5: Client Code


// Application.java
public class Application {
    private Chair chair;
    private Sofa sofa;

    public Application(FurnitureFactory factory) {
        chair = factory.createChair();
        sofa = factory.createSofa();
    }

    public void run() {
        chair.sitOn();
        sofa.lieOn();
    }

    public static void main(String[] args) {
        FurnitureFactory modernFactory = new ModernFurnitureFactory();
        Application modernApp = new Application(modernFactory);
        modernApp.run();

        System.out.println("------");

        FurnitureFactory victorianFactory = new VictorianFurnitureFactory();
        Application victorianApp = new Application(victorianFactory);
        victorianApp.run();
    }
}

Output

Sitting on a modern chair.
Lying on a modern sofa.
------
Sitting on a Victorian chair.
Lying on a Victorian sofa.

📖 Explanation

  • Chair & Sofa are the product interfaces.
  • ModernChair, VictorianSofa, etc., are concrete products.
  • FurnitureFactory is the abstract factory.
  • ModernFurnitureFactory & VictorianFurnitureFactory are concrete factories.
  • The Application is the client that depends only on the abstract factory, not on specific classes.

This ensures:

  • Consistency: Modern factory only returns modern products.
  • Flexibility: We can add new families like FuturisticFurnitureFactory without changing client code.

✅ Benefits

  • Loose coupling: Client code doesn’t need to know about concrete classes.
  • Scalability: New product families can be added easily.
  • Consistency: Ensures that related products are used together.

⚠ Drawbacks

  • Can become complex with too many products.
  • Adding a new product type (e.g., Table) requires changes in all factories.

🏁 Conclusion

The Abstract Factory Pattern is a powerful tool when you need to create families of related objects without binding your code to their concrete classes.

It might seem verbose initially, but the long-term flexibility and maintainability it offers is worth the effort.

This is Part 3 of the Java Design Patterns Series.

If you find it insightful, please share your feedback. Also let me know if you have used factory pattern in your projects.

Next Up: Prototype Pattern – Cloning Without the Mess!


This content originally appeared on DEV Community and was authored by Priyank Bhardwaj