The Factory Pattern .
Creating objects without exposing the creation logic.

Have you ever found yourself writing too many new statements all over your code — creating objects manually every time you need them?
If yes, then you’ve probably faced this problem:
“Every time I add a new type of object, I need to change multiple places in the code. It becomes messy and tightly coupled.”
This is a common pain point in software design. The Factory Design Pattern is here to fix that.
// Step 1: Common Interface
public interface Notification {
void send(String message);
}
// Step 2: Concrete Classes
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Sending EMAIL: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("Sending SMS: " + message);
}
}
public class PushNotification implements Notification {
public void send(String message) {
System.out.println("Sending PUSH: " + message);
}
}
// Step 3: Factory Class
public class NotificationFactory {
public static Notification createNotification(String type) {
if (type == null || type.isEmpty()) return null;
switch (type.toUpperCase()) {
case "EMAIL": return new EmailNotification();
case "SMS": return new SMSNotification();
case "PUSH": return new PushNotification();
default: throw new IllegalArgumentException("Unknown notification type " + type);
}
}
}
// Step 4: Client Code
public class Main {
public static void main(String[] args) {
Notification notification = NotificationFactory.createNotification("EMAIL");
notification.send("Factory Pattern in Action!");
}
}
🧠 What Just Happened?
Now, your Main or NotificationService doesn’t need to know how notifications are created — it just asks the factory for one.
If tomorrow you add WhatsAppNotification, you just update the factory, not every place in your app.
Important for the Spring Boot developer
💬 Your Question:
“If we’re using frameworks like Spring, then we don’t face the problem of using
neweverywhere. So, do we still need the Factory Pattern?”
Let’s unpack this clearly — because this is exactly where most developers get confused when learning design patterns in the age of frameworks like Spring Boot.
Spring itself already uses the Factory Pattern internally — that’s why you don’t have to use new.
But understanding the Factory Pattern is still essential — because Spring’s entire dependency injection system is built on top of it.
🧩 Without Spring — Manual Object Creation
When you don’t use Spring, you do something like this:
Notification notification = new EmailNotification();
notification.send("Hello!");
or
if (type.equals("SMS")) {
notification = new SMSNotification();
}
👉 You’re manually creating objects with new.
If you add a new type tomorrow, you have to modify your code — it’s tightly coupled.
🏭 With Spring — Factory in Action (But Hidden)
When you use Spring:
@Service
public class NotificationService {
@Autowired
private Notification notification;
}
You never write new EmailNotification() — right?
That’s because the Spring Container (ApplicationContext) acts like a Super Factory:
It creates objects for you (beans).
It decides which implementation to inject.
It manages their lifecycle (singleton, prototype, etc.).
Under the Hood
Spring uses:
BeanFactory → The root factory that creates and manages beans.
ApplicationContext → A more advanced factory that supports AOP, events, and message sources.
So yes — the Factory Pattern is at the core of Spring’s architecture.
You don’t see it, but it’s running behind every @Autowired.
🧠 Why You Should Still Learn the Factory Pattern
Even though Spring handles object creation for you, understanding the Factory Pattern helps you:
Understand Spring’s internals
→ You’ll know howBeanFactory,ApplicationContext, and dependency injection work.Write cleaner custom factories
→ Sometimes, you still need to decide at runtime which object to create based on user input or configuration.
Example: Payment gateway selector — Stripe, Razorpay, or PayPal.public interface PaymentGateway { void pay(); } public class StripeGateway implements PaymentGateway { public void pay() { ... } } public class RazorpayGateway implements PaymentGateway { public void pay() { ... } } @Component public class PaymentFactory { public PaymentGateway getGateway(String type) { return switch (type) { case "STRIPE" -> new StripeGateway(); case "RAZORPAY" -> new RazorpayGateway(); default -> throw new IllegalArgumentException("Unknown gateway: " + type); }; } }You can still inject this factory into services, but the decision logic is yours.
Design framework-agnostic systems
→ In interviews or low-level architecture design, you may be asked to design without frameworks.
Understanding the pattern helps you explain and design the logic yourself.
🏁 Final Thought
“If you find yourself changing the same class every time you add a new type of object — it’s time to use the Factory Pattern.”
The Factory Design Pattern helps you build clean, maintainable, and scalable systems by letting your code focus on behavior, not object creation.



