Abstract Factory Design Pattern
Read the Factory Method Pattern before reading this article :)
THE WHAT
The Abstract Factory is a creational design pattern that allows you to produce families of related objects without specifying their concrete classes. This pattern provides a way to encapsulate a group of individual factories that have a common theme. By using the Abstract Factory, you can create objects that belong to the same family without relying on their specific implementations.
THE WHEN — The General Problem it Tries to Solve
The Abstract Factory pattern addresses the problem of creating families of related objects without being tightly coupled to their specific classes. In complex applications, different parts of the system may need to interact with various sets of related objects. Hardcoding the creation of these objects can lead to inflexible code that is difficult to maintain and extend. The Abstract Factory pattern provides a way to create these objects dynamically based on the configuration or environment, promoting flexibility and scalability.
Example of the General Problem
Consider a document viewer application that needs to support multiple themes (e.g., light and dark). Each theme requires a consistent set of UI components, such as buttons, windows, and dialogs, that are visually and functionally compatible with each other. Hardcoding the creation of these components for each theme would result in duplicated code and make it difficult to add new themes in the future. Using the Abstract Factory pattern, you can create a factory for each theme that produces the appropriate UI components, ensuring compatibility and ease of extension.
Generalizing the When
Use the Abstract Factory pattern when:
THE HOW
public interface Button {
void render();
}
public interface Window {
void open();
}
2. Create Concrete Products: Implement these interfaces in concrete product classes for each variant.
领英推荐
public class LightButton implements Button {
@Override
public void render() {
System.out.println("Rendering light theme button.");
}
}
public class DarkButton implements Button {
@Override
public void render() {
System.out.println("Rendering dark theme button.");
}
}
public class LightWindow implements Window {
@Override
public void open() {
System.out.println("Opening light theme window.");
}
}
public class DarkWindow implements Window {
@Override
public void open() {
System.out.println("Opening dark theme window.");
}
}
3. Define the Abstract Factory Interface: Declare an interface for creating abstract products.
public interface UIFactory {
Button createButton();
Window createWindow();
}
4. Implement Concrete Factories: Create concrete factories that implement the abstract factory interface for each variant.
public class LightThemeFactory implements UIFactory {
@Override
public Button createButton() {
return new LightButton();
}
@Override
public Window createWindow() {
return new LightWindow();
}
}
public class DarkThemeFactory implements UIFactory {
@Override
public Button createButton() {
return new DarkButton();
}
@Override
public Window createWindow() {
return new DarkWindow();
}
}
5. Initialize the Factory: In the application initialization code, instantiate the appropriate concrete factory based on the configuration or environment.
public class Application {
private UIFactory uiFactory;
public Application(UIFactory factory) {
this.uiFactory = factory;
}
public void run() {
Button button = uiFactory.createButton();
Window window = uiFactory.createWindow();
button.render();
window.open();
}
public static void main(String[] args) {
UIFactory factory;
String theme = "dark"; // This could be read from a configuration file or user input
if (theme.equals("light")) {
factory = new LightThemeFactory();
} else {
factory = new DarkThemeFactory();
}
Application app = new Application(factory);
app.run();
}
}
Consequences
Pros
Cons
Tradeoffs
While the Abstract Factory pattern provides significant flexibility and decoupling benefits, it also introduces complexity and overhead. It’s essential to balance these tradeoffs based on the specific requirements and constraints of your project.
Thank you