Skip to main content

Abstract Factory Pattern

The Abstract Factory Pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern is particularly useful when a system needs to be independent of how its products are created, composed, and represented.

Abstract Factory Pattern Diagram

Key Concepts

  • Abstract Factory: An interface for creating a family of related objects.
  • Concrete Factory: Implements the Abstract Factory interface to create concrete products.
  • Product: The objects created by the factories.

Example

Imagine you're developing a UI toolkit that needs to support multiple themes (e.g., Windows, Mac, and Linux). Each theme has different styles for buttons, windows, and menus. Instead of hardcoding these styles, you can use the Abstract Factory Pattern to create a family of related objects for each theme.

// Abstract Factory Interface
public interface UIFactory {
Button createButton();
Window createWindow();
Menu createMenu();
}

// Concrete Factories
public class WindowsFactory implements UIFactory {
public Button createButton() {
return new WindowsButton();
}
public Window createWindow() {
return new WindowsWindow();
}
public Menu createMenu() {
return new WindowsMenu();
}
}

public class MacFactory implements UIFactory {
public Button createButton() {
return new MacButton();
}
public Window createWindow() {
return new MacWindow();
}
public Menu createMenu() {
return new MacMenu();
}
}

// Products
public class WindowsButton implements Button {}
public class WindowsWindow implements Window {}
public class WindowsMenu implements Menu {}

public class MacButton implements Button {}
public class MacWindow implements Window {}
public class MacMenu implements Menu {}

Usage

public class Application {
private UIFactory factory;

public Application(UIFactory factory) {
this.factory = factory;
}

public void run() {
Button button = factory.createButton();
Window window = factory.createWindow();
Menu menu = factory.createMenu();
// Use the created objects
}
}

// Client Code
public class Client {
public static void main(String[] args) {
UIFactory factory;
if (OS.isWindows()) {
factory = new WindowsFactory();
} else if (OS.isMac()) {
factory = new MacFactory();
} else {
throw new UnsupportedOperationException("Unsupported OS");
}
Application app = new Application(factory);
app.run();
}
}

Differences Between Abstract Factory and Factory Pattern

AspectAbstract Factory PatternFactory Pattern
PurposeCreate families of related objectsCreate a single product or family
StructureMultiple factories with a common interfaceSingle factory with a common interface
Use CaseDifferent families of products (e.g., UI themes)Single type of product (e.g., shapes)
FlexibilityHigher flexibility with multiple factoriesLess flexible with a single factory
ComplexityMore complex due to multiple factoriesSimpler due to a single factory

Conclusion


info

The Abstract Factory Pattern is a powerful design pattern that allows for the creation of families of related or dependent objects without specifying their concrete classes. It provides a way to encapsulate a group of individual factories that have a common theme, making it easier to manage and extend product families. By using abstract factories, you can ensure that your application is more flexible, scalable, and maintainable, as it decouples the client code from the specific implementations of the products.

This pattern is particularly useful in scenarios where you need to support multiple families of related products (e.g., different UI themes or cross-platform support), as it provides a consistent interface for creating these products, allowing for easier integration and modification in the future. By adhering to the principles of the Abstract Factory Pattern, you can build robust, modular, and adaptable systems that can accommodate change with minimal effort.