Last updated: 26.02.2026
The Abstract Factory pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes.
It is particularly useful when a system needs to be independent of how its products are created, composed, and represented.
Let's say we are building an E-commerce system that supports multiple payment providers like:
- Stripe
- Razorpay
Each provider requires a family of related components:
- PaymentProcessor
- RefundProcessor
- WebhookHandler
❌ What can go wrong?
If we don’t use Abstract Factory:
PaymentProcessor processor = new StripePaymentProcessor();
RefundProcessor refund = new RazorpayRefundProcessor(); // ❌ Wrong combinationNow:
- Payment is processed via Stripe
- Refund is attempted via Razorpay
- System becomes inconsistent
- Real production bug 🚨
We must ensure:
- If Stripe is selected → ALL Stripe components are used
- If Razorpay is selected → ALL Razorpay components are used
This requirement of creating consistent families of related objects is exactly why we use Abstract Factory Pattern.
├── product
│ ├── PaymentProcessor.java
│ ├── RefundProcessor.java
│ └── WebhookHandler.java
│
├── stripe
│ ├── StripePaymentProcessor.java
│ ├── StripeRefundProcessor.java
│ └── StripeWebhookHandler.java
│
├── razorpay
│ ├── RazorpayPaymentProcessor.java
│ ├── RazorpayRefundProcessor.java
│ └── RazorpayWebhookHandler.java
│
├── factory
│ ├── PaymentGatewayFactory.java
│ ├── StripePaymentGatewayFactory.java
│ └── RazorpayPaymentGatewayFactory.java
│
└── client
└── Application.java
1️⃣ PaymentProcessor
public interface PaymentProcessor {
void processPayment(double amount);
}2️⃣ RefundProcessor
public interface RefundProcessor {
void processRefund(String transactionId);
}3️⃣ WebhookHandler
public interface WebhookHandler {
void handleWebhook(String payload);
}StripePaymentProcessor
public class StripePaymentProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing payment via Stripe: ₹" + amount);
}
}StripeRefundProcessor
public class StripeRefundProcessor implements RefundProcessor {
@Override
public void processRefund(String transactionId) {
System.out.println("Processing refund via Stripe for transaction: " + transactionId);
}
}StripeWebhookHandler
public class StripeWebhookHandler implements WebhookHandler {
@Override
public void handleWebhook(String payload) {
System.out.println("Handling Stripe webhook: " + payload);
}
}RazorpayPaymentProcessor
public class RazorpayPaymentProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing payment via Razorpay: ₹" + amount);
}
}RazorpayRefundProcessor
public class RazorpayRefundProcessor implements RefundProcessor {
@Override
public void processRefund(String transactionId) {
System.out.println("Processing refund via Razorpay for transaction: " + transactionId);
}
}RazorpayWebhookHandler
public class RazorpayWebhookHandler implements WebhookHandler {
@Override
public void handleWebhook(String payload) {
System.out.println("Handling Razorpay webhook: " + payload);
}
}public interface PaymentGatewayFactory {
PaymentProcessor createPaymentProcessor();
RefundProcessor createRefundProcessor();
WebhookHandler createWebhookHandler();
}Stripe Factory
public class StripePaymentGatewayFactory implements PaymentGatewayFactory {
@Override
public PaymentProcessor createPaymentProcessor() {
return new StripePaymentProcessor();
}
@Override
public RefundProcessor createRefundProcessor() {
return new StripeRefundProcessor();
}
@Override
public WebhookHandler createWebhookHandler() {
return new StripeWebhookHandler();
}
}Razorpay Factory
public class RazorpayPaymentGatewayFactory implements PaymentGatewayFactory {
@Override
public PaymentProcessor createPaymentProcessor() {
return new RazorpayPaymentProcessor();
}
@Override
public RefundProcessor createRefundProcessor() {
return new RazorpayRefundProcessor();
}
@Override
public WebhookHandler createWebhookHandler() {
return new RazorpayWebhookHandler();
}
}public class EcommerceApplication {
public static void main(String[] args) {
// Choose payment provider
PaymentGatewayFactory factory = new StripePaymentGatewayFactory();
PaymentProcessor paymentProcessor = factory.createPaymentProcessor();
RefundProcessor refundProcessor = factory.createRefundProcessor();
WebhookHandler webhookHandler = factory.createWebhookHandler();
paymentProcessor.processPayment(5000);
refundProcessor.processRefund("TXN12345");
webhookHandler.handleWebhook("payment_success_event");
}
}Processing payment via Stripe: ₹5000.0
Processing refund via Stripe for transaction: TXN12345
Handling Stripe webhook: payment_success_event
- Payment gateway providers Stripe / Razorpay / PayPal
- UI Themes
- Database Drivers - MySqlFactory, PostgreSql Factory, They created Connection, QueryExecutor, TransactionManager
- You Need Families of Related Objects
- Objects Must Be Used Together They are designed to work as a group.
- You Want to Enforce Consistency: Prevent mixing incompatible implementations.
- You Want System-Level Switching: Switch provider by changing just one line.
- You Want High-Level Decoupling: Client should not know:
- Concrete classes
- How objects are created
- How they relate internally
- Only one product exists
- Only one implementation exists
- Products are unrelated
- Simpler Factory Method is sufficient
- Ensures Product Compatibility: Prevents mixing unrelated components.
- Strong Abstraction: Client depends only on interfaces.
- Open/Closed Principle: Add new provider without modifying existing code.
- Easy Environment Switching: Change factory → whole system switches.
- Clean Architecture: Separates object creation and business logic.
- More Classes: More interfaces and classes.
- Difficult to Extend: Adding new products requires modifying all factories.
- Tight Coupling: Products are tightly coupled to their factory.
- Not Suitable for Simple Systems: Overkill for simple object creation.
Abstract Factory is used when we need to create families of releated objects that must work together. It ensures consistency and prevents mixing incompatible implementations. In our payment gateway example, it guarantees that Stripe payment, refund, and webhook components are always used together.
🔗 https://algomaster.io/learn/lld/abstract-factory
🔗 https://refactoring.guru/design-patterns/abstract-factory
🔗 https://codewitharyan.com/tech-blogs/abstract-factory-pattern
🎥 https://www.youtube.com/watch?v=or1wpvH2Yps
