Abstract Factory Pattern
IntermediateProvides an interface for creating families of related objects without specifying their concrete classes.
Overview
Abstract Factory is a super-factory that creates other factories. It groups Factory Methods for related products under one interface. The classic example is a UI toolkit: an AbstractUIFactory declares createButton() and createCheckbox(); WindowsFactory returns Windows-styled widgets, MacFactory returns Mac-styled widgets. The client receives a factory (injected or chosen at startup) and creates a consistent family of products without knowing platform specifics. Abstract Factory enforces product family consistency — you cannot mix Windows buttons with Mac checkboxes.
Abstract Factory Implementation
Define abstract product interfaces for each product in the family. Define an AbstractFactory interface with one create method per product. Implement concrete factories per family. The client receives the factory via constructor injection.
// Abstract Products
public interface Button {
void render();
void onClick();
}
public interface Checkbox {
void render();
boolean isChecked();
}
// Concrete Products — Windows family
public class WindowsButton implements Button {
@Override public void render() { System.out.println("Rendering Windows Button"); }
@Override public void onClick() { System.out.println("Windows Button clicked"); }
}
public class WindowsCheckbox implements Checkbox {
private boolean checked = false;
@Override public void render() { System.out.println("Rendering Windows Checkbox"); }
@Override public boolean isChecked() { return checked; }
}
// Concrete Products — Mac family
public class MacButton implements Button {
@Override public void render() { System.out.println("Rendering Mac Button"); }
@Override public void onClick() { System.out.println("Mac Button clicked"); }
}
public class MacCheckbox implements Checkbox {
private boolean checked = false;
@Override public void render() { System.out.println("Rendering Mac Checkbox"); }
@Override public boolean isChecked() { return checked; }
}
// Abstract Factory
public interface UIFactory {
Button createButton();
Checkbox createCheckbox();
}
// Concrete Factories
public class WindowsFactory implements UIFactory {
@Override public Button createButton() { return new WindowsButton(); }
@Override public Checkbox createCheckbox() { return new WindowsCheckbox(); }
}
public class MacFactory implements UIFactory {
@Override public Button createButton() { return new MacButton(); }
@Override public Checkbox createCheckbox() { return new MacCheckbox(); }
}
// Client — depends only on interfaces
public class Application {
private final Button button;
private final Checkbox checkbox;
public Application(UIFactory factory) {
this.button = factory.createButton();
this.checkbox = factory.createCheckbox();
}
public void render() {
button.render();
checkbox.render();
}
}
// Wiring at startup
UIFactory factory = System.getProperty("os.name").startsWith("Mac")
? new MacFactory()
: new WindowsFactory();
Application app = new Application(factory);
app.render();Abstract Factory vs Factory Method
Factory Method uses inheritance to vary a single product; Abstract Factory uses composition to vary a family of products. Abstract Factory is essentially a set of Factory Methods grouped by family. Use Abstract Factory when the system must be independent of product creation and must work with multiple product families.
// Factory Method — one product, subclass decides
abstract class Dialog {
abstract Button createButton(); // single factory method
void render() { createButton().render(); }
}
// Abstract Factory — multiple related products, injected factory
interface ThemeFactory {
Button createButton();
TextBox createTextBox();
Menu createMenu();
// All products share the same theme/family
}
// Key rule: Abstract Factory products must be used together.
// Mixing MacButton with WindowsTextBox is a logic error the compiler won't catch —
// design your factories to make this impossible.Key Points to Remember
- 1Abstract Factory creates a family of related objects; Factory Method creates one type of object.
- 2Enforces product family consistency — prevents mixing objects from different families.
- 3Adding a new product family requires a new concrete factory class (OCP-compliant).
- 4Adding a new product type requires changing the AbstractFactory interface and ALL concrete factories (costly).
- 5Commonly implemented with dependency injection — inject the factory, not the products directly.
Interview Questions
Sign in to ask AriaWhat is the key difference between Abstract Factory and Factory Method?
How do you add a new product family without modifying existing code in Abstract Factory?
What is the downside of Abstract Factory when you need to add a new product type?
Give a real-world Java example where Abstract Factory is used.
Ask Aria about Abstract Factory Pattern
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.