Full Stack • Java • System Design • Cloud • AI Engineering

Abstract Factory Design Pattern in Java

Learn Abstract Factory Design Pattern in Java with diagrams, real-world examples, framework usage, code examples, benefits, limitations, and interview questions.

Introduction

In the previous article, we learned Factory Method Pattern.

Factory Method creates one object at a time.

But what if we need to create an entire family of related objects together?

Examples:

  • Windows UI Components
  • Mac UI Components
  • AWS Cloud Resources
  • Azure Cloud Resources
  • Insurance Product Families
  • Banking Product Families

This is where the Abstract Factory Pattern comes into play.


Purpose of Abstract Factory Pattern

The main purpose of Abstract Factory is:

Create families of related objects without specifying their concrete classes.

Instead of creating a single object:

Factory Method
    ↓
Creates One Product

Abstract Factory:

Abstract Factory
    ↓
Creates Multiple Related Products

Real World Analogy

Imagine you buy a complete furniture set.

Modern Set:

  • Modern Chair
  • Modern Table
  • Modern Sofa

Classic Set:

  • Classic Chair
  • Classic Table
  • Classic Sofa

You don't buy individual pieces randomly.

You choose an entire family.

This is exactly what Abstract Factory does.


Problem Without Abstract Factory

Suppose we are building a UI application.

We need:

Button
Textbox
Checkbox

For:

Windows
Mac
Linux

Without Abstract Factory:

Button button = new WindowsButton();
Textbox textbox = new MacTextbox();
Checkbox checkbox = new LinuxCheckbox();

This creates inconsistent UI components.


Solution

Create an entire family together.

flowchart TD

A[Client]

A --> B[GUI Factory]

B --> C[Button]

B --> D[Textbox]

B --> E[Checkbox]

Abstract Factory Structure

classDiagram

class GUIFactory {
  <<interface>>
  +createButton()
  +createTextbox()
}

class WindowsFactory
class MacFactory

class Button
class Textbox

GUIFactory <|.. WindowsFactory
GUIFactory <|.. MacFactory

WindowsFactory --> Button
WindowsFactory --> Textbox

MacFactory --> Button
MacFactory --> Textbox

Step 1: Create Product Interfaces

Button

public interface Button {
    void render();
}

TextBox

public interface TextBox {
    void render();
}

Step 2: Create Windows Products

public class WindowsButton implements Button {

    @Override
    public void render() {
        System.out.println("Windows Button Rendered");
    }
}
public class WindowsTextBox implements TextBox {

    @Override
    public void render() {
        System.out.println("Windows TextBox Rendered");
    }
}

Step 3: Create Mac Products

public class MacButton implements Button {

    @Override
    public void render() {
        System.out.println("Mac Button Rendered");
    }
}
public class MacTextBox implements TextBox {

    @Override
    public void render() {
        System.out.println("Mac TextBox Rendered");
    }
}

Step 4: Create Abstract Factory

public interface GUIFactory {

    Button createButton();

    TextBox createTextBox();
}

Step 5: Create Concrete Factories

Windows Factory

public class WindowsFactory implements GUIFactory {

    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextBox createTextBox() {
        return new WindowsTextBox();
    }
}

Mac Factory

public class MacFactory implements GUIFactory {

    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public TextBox createTextBox() {
        return new MacTextBox();
    }
}

Step 6: Client Code

public class Application {

    private final Button button;
    private final TextBox textBox;

    public Application(GUIFactory factory) {

        button = factory.createButton();
        textBox = factory.createTextBox();
    }

    public void renderUI() {

        button.render();
        textBox.render();
    }
}

Main Method

public class Demo {

    public static void main(String[] args) {

        GUIFactory factory = new WindowsFactory();

        Application app = new Application(factory);

        app.renderUI();
    }
}

Output

Windows Button Rendered
Windows TextBox Rendered

Object Creation Flow

sequenceDiagram

participant Client
participant WindowsFactory
participant WindowsButton
participant WindowsTextBox

Client->>WindowsFactory:createButton()
WindowsFactory-->>Client:WindowsButton

Client->>WindowsFactory:createTextBox()
WindowsFactory-->>Client:WindowsTextBox

Banking Example

Suppose a bank offers products.

Savings Family:

Savings Account
Savings Debit Card
Savings Rewards

Premium Family:

Premium Account
Premium Debit Card
Premium Rewards

Abstract Factory creates the entire family together.


Banking Diagram

flowchart TD

A[Bank Factory]

A --> B[Savings Products]

A --> C[Premium Products]

B --> D[Savings Account]

B --> E[Savings Card]

C --> F[Premium Account]

C --> G[Premium Card]

Insurance Example

Insurance Products:

Health Package

Health Policy
Health Claims
Health Premium Calculator

Vehicle Package

Vehicle Policy
Vehicle Claims
Vehicle Premium Calculator

Each package is a family of related products.


Cloud Provider Example

Enterprise systems often support:

AWS
Azure
GCP

Abstract Factory can create:

AWS Factory

EC2 Client
S3 Client
RDS Client

Azure Factory

VM Client
Blob Storage Client
SQL Client

Cloud Architecture

flowchart TD

A[Cloud Factory]

A --> B[AWS Factory]

A --> C[Azure Factory]

B --> D[EC2]

B --> E[S3]

C --> F[VM]

C --> G[Blob Storage]

Spring Framework Example

Spring internally uses factory concepts extensively.

Examples:

ApplicationContext
BeanFactory
FactoryBean

FactoryBean Example

@Component
public class CustomerFactoryBean
        implements FactoryBean<Customer> {

    @Override
    public Customer getObject() {

        Customer customer = new Customer();

        customer.setName("CodeWithVenu");

        return customer;
    }

    @Override
    public Class<?> getObjectType() {
        return Customer.class;
    }
}

Spring creates objects through factory mechanisms behind the scenes.


Factory Method vs Abstract Factory

Feature Factory Method Abstract Factory
Creates One Product Product Family
Complexity Simple Moderate
Number of Objects One Multiple
Use Case Notification Type UI Component Family

Factory Method Example

Notification Factory

EMAIL
SMS
PUSH

Creates one notification object.


Abstract Factory Example

Windows Factory

Windows Button
Windows Textbox
Windows Checkbox

Creates a family of related objects.


Benefits

✅ Consistent Product Families

✅ Loose Coupling

✅ Easy To Extend

✅ Follows Open Closed Principle

✅ Centralized Object Creation

✅ Cleaner Code


Limitations

❌ More Classes

❌ More Complexity

❌ Overkill For Small Projects

❌ Harder To Understand Initially


When To Use

Use Abstract Factory when:

  • Multiple product families exist
  • Related objects must work together
  • Object creation is complex
  • Families may change dynamically

Examples:

  • UI Frameworks
  • Cloud Providers
  • Banking Products
  • Insurance Products
  • Database Providers

When Not To Use

Avoid Abstract Factory when:

  • Only one object needs creation
  • Product families don't exist
  • Simpler Factory Method is sufficient

Interview Questions

What is Abstract Factory?

A Creational Design Pattern that creates families of related objects without specifying concrete classes.


Difference Between Factory Method and Abstract Factory?

Factory Method creates one object.

Abstract Factory creates a family of related objects.


Give Real World Example

Windows UI Factory:

  • Button
  • TextBox
  • Checkbox

Mac UI Factory:

  • Button
  • TextBox
  • Checkbox

Is Abstract Factory Used In Spring?

Yes.

Examples include:

  • BeanFactory
  • FactoryBean
  • ApplicationContext

Key Takeaways

  • Abstract Factory creates families of related objects.
  • It provides consistency across products.
  • It hides complex object creation logic.
  • It promotes loose coupling.
  • Widely used in enterprise systems and frameworks.
  • Factory Method creates one object.
  • Abstract Factory creates multiple related objects together.