Abstract Factory Design Pattern in Java

This article explains Abstract Factory design pattern in java with UML class diagram. It then takes an example scenario in java and explains it with class diagram and code.
Introduction Abstract Factory Design Pattern is a creational design pattern among the Gang Of Four(GOF) Design PatternsClick to read: Gang Of Four(GOF) Design Patterns. Being a creational design pattern, the Abstract Factory pattern deals with how objects are created - specifically, how a whole family of related objects is created consistently. What is Abstract Factory Design Pattern The Abstract Factory design pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. A factory object has one creation method for each kind of product in the family. Each concrete factory creates products which belong together, so client code which works only with the factory and product interfaces automatically gets a consistent set of objects, and the whole family can be switched by switching the factory.

It is closely related to the Factory Method patternClick to read: Factory Method pattern: an abstract factory is typically implemented as a set of factory methods, one per product. The difference is in scope - a factory method creates one product, while an abstract factory creates a family of products which must be used together. Scenarios in which Abstract Factory Design Pattern can be used
  1. Families of related products: The system works with several kinds of products - buttons, checkboxes and menus, or connections, commands and readers - which come in several variants, and the products of one variant must be used together.
  2. Independence from concrete classes: The client code should not depend on how its products are created or which concrete classes they are, so that variants can be added without changing it.
  3. Configuring the system with one family: The choice of family is made once - from configuration, the platform, or a user setting - and the rest of the application must consistently use that family.
Class Diagram for Abstract Factory Design Pattern
Abstract Factory Design Pattern Class Diagram
Explanation of Abstract Factory Design Pattern's Class Diagram
  • AbstractFactory declares one creation method per product type - createProductA() and createProductB() - each returning an abstract product.
  • ConcreteFactory1 and ConcreteFactory2 implement it. Each creates the products of one family: ConcreteFactory1 creates ProductA1 and ProductB1, ConcreteFactory2 creates ProductA2 and ProductB2.
  • AbstractProductA and AbstractProductB are the interfaces for each kind of product, implemented by one class per family.
  • Client uses only the abstract interfaces. It is given a concrete factory once, and every product it creates through it belongs to the same family.
Abstract Factory Design Pattern in Java - Class Diagram
Abstract Factory Design Pattern in Java Class Diagram
The example builds a settings screen which supports a light and a dark theme. A button and a checkbox from different themes would look wrong together, so each theme is a family of UI components, created by its own factory.
Code for the classes shown in Java Example's Class Diagram
Button.java - an abstract product
//Button.java
public interface Button {
 String render();
}
Checkbox.java - an abstract product
//Checkbox.java
public interface Checkbox {
 String render();
}
LightButton.java and LightCheckbox.java - the light family
//LightButton.java
class LightButton implements Button {
 public String render() { return "[ Save ]  (white background, dark text)"; }
}
//LightCheckbox.java
class LightCheckbox implements Checkbox {
 public String render() { return "[x] Notifications  (grey border)"; }
}
DarkButton.java and DarkCheckbox.java - the dark family
//DarkButton.java
class DarkButton implements Button {
 public String render() { return "[ Save ]  (charcoal background, light text)"; }
}
//DarkCheckbox.java
class DarkCheckbox implements Checkbox {
 public String render() { return "[x] Notifications  (glowing blue border)"; }
}
UIFactory.java - the abstract factory and its two implementations
//UIFactory.java
public interface UIFactory {
 Button createButton();
 Checkbox createCheckbox();
}
//LightThemeFactory.java
class LightThemeFactory implements UIFactory {
 public Button createButton() { return new LightButton(); }
 public Checkbox createCheckbox() { return new LightCheckbox(); }
}
//DarkThemeFactory.java
class DarkThemeFactory implements UIFactory {
 public Button createButton() { return new DarkButton(); }
 public Checkbox createCheckbox() { return new DarkCheckbox(); }
}
SettingsScreen.java (with the main() method)
//SettingsScreen.java
public class SettingsScreen {
 private final Button saveButton;
 private final Checkbox notifications;

 // The screen depends only on the abstract factory and abstract products
 SettingsScreen(UIFactory factory) {
  this.saveButton = factory.createButton();
  this.notifications = factory.createCheckbox();
 }

 void draw() {
  System.out.println("  " + notifications.render());
  System.out.println("  " + saveButton.render());
 }

 static UIFactory factoryFor(String theme) {          // the family is chosen in one place
  return theme.equals("dark") ? new DarkThemeFactory() : new LightThemeFactory();
 }

 public static void main(String[] args) {
  for (String theme : new String[] {"light", "dark"}) {
   System.out.println("Theme: " + theme);
   new SettingsScreen(factoryFor(theme)).draw();
  }
 }
}
 OUTPUT on running SettingsScreen.java
Theme: light
  [x] Notifications  (grey border)
  [ Save ]  (white background, dark text)
Theme: dark
  [x] Notifications  (glowing blue border)
  [ Save ]  (charcoal background, light text)
Explanation of Java Example's Class Diagram & Code
  • UIFactory is the abstract factory, with one method per kind of component. LightThemeFactory and DarkThemeFactory are the concrete factories, one per family.
  • Button and Checkbox are the abstract products; LightButton, DarkButton, LightCheckbox and DarkCheckbox are the concrete products.
  • SettingsScreen is the client. It receives a factory in its constructor and never names a concrete class, so it cannot mix a light button with a dark checkbox - each screen's components always come from one family.
  • The theme is chosen in one place, factoryFor(). Adding a third theme - say, a high-contrast one - means adding one factory and its products, with no change to SettingsScreen.
  • The flip side: adding a new kind of product, such as a slider, requires a new method in UIFactory and in every concrete factory. Abstract Factory makes new families easy, and new product types harder.
Note - The JDK uses Abstract Factory in several APIs. For example, javax.xml.parsers.DocumentBuilderFactory creates XML parsers from whichever implementation is configured, and JDBC's Connection acts as a factory for the Statements and other objects of one database driver.
Summary In the above tutorial we understood what is Abstract Factory design pattern and the main scenarios in which it is applicable. We then looked at the UML class diagram for Abstract Factory Design Pattern & its explanation, a Java use case implementing the Abstract Factory pattern for light and dark UI themes with its class diagram, code and output, followed by an explanation of both the class diagram & code. This concludes the tutorial on Abstract Factory design pattern.