Introduction
In real-world applications, creating objects directly using new can tightly couple your code, making it hard to scale and maintain. As projects grow, this leads to messy conditionals, duplication, and poor flexibility.
The Factory Design Pattern solves this by centralizing object creation logic—allowing you to create objects without exposing instantiation details to the client.
What is Factory Design Pattern?
The Factory Design Pattern is a creational design pattern that provides an interface for creating objects, but lets subclasses decide which class to instantiate.
In simple words:
👉 “Instead of creating objects directly, you ask a factory to create them for you.”
Why Do We Need Factory Pattern?
In my decade of teaching Java, I’ve seen developers struggle with:
- Tight coupling between classes
- Repeated object creation logic
- Difficulty in adding new features
Factory Pattern solves:
- Loose coupling
- Centralized object creation
- Easy scalability
Real-Time Scenario
Our students in Hyderabad often relate to this example:
🚗 Vehicle Manufacturing System
Imagine you are building a system for a vehicle company.
You have multiple vehicle types:
- Car
- Bike
- Truck
Instead of creating objects like:
Vehicle v = new Car();
You use a factory:
Vehicle v = VehicleFactory.getVehicle("CAR");
Step-by-Step Implementation
Step 1: Create an Interface
public interface Vehicle {
void drive();
}
Step 2: Create Concrete Classes
public class Car implements Vehicle {
public void drive() {
System.out.println("Driving Car");
}
}
public class Bike implements Vehicle {
public void drive() {
System.out.println("Riding Bike");
}
}
public class Truck implements Vehicle {
public void drive() {
System.out.println("Driving Truck");
}
}
Step 3: Create Factory Class
public class VehicleFactory {
public static Vehicle getVehicle(String type) {
if (type == null) return null;
switch (type.toUpperCase()) {
case "CAR":
return new Car();
case "BIKE":
return new Bike();
case "TRUCK":
return new Truck();
default:
throw new IllegalArgumentException("Invalid vehicle type");
}
}
}
Step 4: Client Code
public class Main {
public static void main(String[] args) {
Vehicle v1 = VehicleFactory.getVehicle("CAR");
v1.drive();
Vehicle v2 = VehicleFactory.getVehicle("BIKE");
v2.drive();
}
}
Expert Explanation
In my experience building enterprise apps:
- The client doesn’t know which class is instantiated
- Object creation logic is encapsulated in one place
- Easy to extend without modifying client code
Edge Cases You Must Handle
❗ 1. Invalid Input
VehicleFactory.getVehicle("PLANE"); // Exception
✔ Always validate input and throw meaningful exceptions
❗ 2. Null Values
VehicleFactory.getVehicle(null);
✔ Handle nulls to avoid NullPointerException
❗ 3. Too Many Conditions
If you add many types:
if-else or switch becomes messy
✔ Solution: Use Map or Reflection-based factory
Improved Factory Using Map
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public class BetterVehicleFactory {
private static final Map<String, Supplier<Vehicle>> registry = new HashMap<>();
static {
registry.put("CAR", Car::new);
registry.put("BIKE", Bike::new);
registry.put("TRUCK", Truck::new);
}
public static Vehicle getVehicle(String type) {
Supplier<Vehicle> supplier = registry.get(type.toUpperCase());
if (supplier != null) {
return supplier.get();
}
throw new IllegalArgumentException("Invalid vehicle type");
}
}
Key Advantages
- Loose coupling
- Better code readability
- Easy to add new classes
- Follows Open/Closed Principle
Disadvantages
- Adds extra classes
- Can increase complexity for small apps
Factory vs Singleton (Quick Comparison)
| Feature | Factory Pattern | Singleton Pattern |
|---|---|---|
| Purpose | Object creation | Single instance |
| Flexibility | High | Low |
| Usage | Multiple objects | One object only |
| Example | VehicleFactory | Logger instance |
Where Factory Pattern is Used in Real Projects
- Spring Framework (
BeanFactory,ApplicationContext) - Logging frameworks
- Payment gateway integrations
- Notification systems (Email, SMS, Push)
When to Use Factory Pattern
Use it when:
- You don’t know exact object type at runtime
- You want to centralize object creation
- You need to follow clean architecture
When NOT to Use
Avoid when:
- Object creation is simple
- Only one class is needed
- Over-engineering small applications
Quick FAQ
1. What is Factory Pattern in simple terms?
It creates objects without exposing instantiation logic.
2. Is Factory Pattern used in Spring?
Yes, Spring internally uses Factory patterns for bean creation.
3. What is the difference between Factory and Abstract Factory?
Factory creates one product, Abstract Factory creates families of related objects.
4. Is Factory Pattern thread-safe?
Depends on implementation.
5. Can Factory Pattern replace Singleton?
No, both serve different purposes.
Final Thoughts
The Factory Design Pattern is one of the most practical patterns you’ll use in real-world Java development. It improves flexibility, scalability, and maintainability.
If you want to master design patterns with real-time scenarios and crack interviews confidently, I recommend exploring:
https://www.ashokit.in/courses/core-java-online-training
Follow the complete roadmap to become a Java Full Stack Developer:
https://www.ashokit.in/java-full-stack-developer-roadmap
Top comments (0)