☕ Introduction
Design patterns are like battle-tested solutions to common problems in software design. One such pattern is the Abstract Factory Pattern, which falls under Creational Design Patterns. In this article, we’ll break it down with a real-world analogy, implement it in Java, and explain each step thoroughly.
🧠 What is the Abstract Factory Pattern?
The Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.
Think of it as a super-factory, also known as a factory of factories.
🎯 When to Use?
- When your code needs to work with various families of related products.
- When you want to enforce consistency among objects.
- When you want to hide the creation logic from the client code.
🏠 Real-Life Analogy
Imagine a Furniture Store
You sell Modern and Victorian styles of furniture. Each style has:
- A Chair
- A Sofa
You don’t want customers (client code) to create ModernChair or VictorianSofa directly. Instead, you give them a FurnitureFactory, which gives them appropriate combinations of products.
🧱 Class Diagram Overview
+---------------------+
| FurnitureFactory |<-- Abstract Factory
+---------------------+
| + createChair() |
| + createSofa() |
+---------------------+
/ \
/ \
+------------------------+ +---------------------------+
| ModernFurnitureFactory | | VictorianFurnitureFactory |
+------------------------+ +---------------------------+
| + createChair() | | + createChair() |
| + createSofa() | | + createSofa() |
+------------------------+ +---------------------------+
^ ^
| |
+---------------+ +-----------------+
| ModernChair | | VictorianChair |
+---------------+ +-----------------+
+---------------+ +-----------------+
| ModernSofa | | VictorianSofa |
+---------------+ +-----------------+
🧑💻 Let's Implement It in Java
Step 1: Abstract Product Interfaces
// Chair.java
public interface Chair {
void sitOn();
}
// Sofa.java
public interface Sofa {
void lieOn();
}
Step 2: Concrete Products
// ModernChair.java
public class ModernChair implements Chair {
public void sitOn() {
System.out.println("Sitting on a modern chair.");
}
}
// VictorianChair.java
public class VictorianChair implements Chair {
public void sitOn() {
System.out.println("Sitting on a Victorian chair.");
}
}
// ModernSofa.java
public class ModernSofa implements Sofa {
public void lieOn() {
System.out.println("Lying on a modern sofa.");
}
}
// VictorianSofa.java
public class VictorianSofa implements Sofa {
public void lieOn() {
System.out.println("Lying on a Victorian sofa.");
}
}
Step 3: Abstract Factory
// FurnitureFactory.java
public interface FurnitureFactory {
Chair createChair();
Sofa createSofa();
}
Step 4: Concrete Factories
// ModernFurnitureFactory.java
public class ModernFurnitureFactory implements FurnitureFactory {
public Chair createChair() {
return new ModernChair();
}
public Sofa createSofa() {
return new ModernSofa();
}
}
// VictorianFurnitureFactory.java
public class VictorianFurnitureFactory implements FurnitureFactory {
public Chair createChair() {
return new VictorianChair();
}
public Sofa createSofa() {
return new VictorianSofa();
}
}
Step 5: Client Code
// Application.java
public class Application {
private Chair chair;
private Sofa sofa;
public Application(FurnitureFactory factory) {
chair = factory.createChair();
sofa = factory.createSofa();
}
public void run() {
chair.sitOn();
sofa.lieOn();
}
public static void main(String[] args) {
FurnitureFactory modernFactory = new ModernFurnitureFactory();
Application modernApp = new Application(modernFactory);
modernApp.run();
System.out.println("------");
FurnitureFactory victorianFactory = new VictorianFurnitureFactory();
Application victorianApp = new Application(victorianFactory);
victorianApp.run();
}
}
Output
Sitting on a modern chair.
Lying on a modern sofa.
------
Sitting on a Victorian chair.
Lying on a Victorian sofa.
📖 Explanation
- Chair & Sofa are the product interfaces.
- ModernChair, VictorianSofa, etc., are concrete products.
- FurnitureFactory is the abstract factory.
- ModernFurnitureFactory & VictorianFurnitureFactory are concrete factories.
- The Application is the client that depends only on the abstract factory, not on specific classes.
This ensures:
- Consistency: Modern factory only returns modern products.
- Flexibility: We can add new families like
FuturisticFurnitureFactory
without changing client code.
✅ Benefits
- Loose coupling: Client code doesn't need to know about concrete classes.
- Scalability: New product families can be added easily.
- Consistency: Ensures that related products are used together.
⚠️ Drawbacks
- Can become complex with too many products.
- Adding a new product type (e.g., Table) requires changes in all factories.
🏁 Conclusion
The Abstract Factory Pattern is a powerful tool when you need to create families of related objects without binding your code to their concrete classes.
It might seem verbose initially, but the long-term flexibility and maintainability it offers is worth the effort.
This is Part 3 of the Java Design Patterns Series.
If you find it insightful, please share your feedback. Also let me know if you have used factory pattern in your projects.
Next Up: Prototype Pattern – Cloning Without the Mess!
Top comments (0)