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 belongs to the Gang of Four (GoF) patterns and promotes loose coupling, consistency, and extensibility in object-oriented systems.
Core Intent
“Provide an interface for creating families of related or dependent objects without specifying their concrete classes.”
This enables the client to work with high-level abstractions while allowing the system to instantiate consistent product groups at runtime.
When to Use Abstract Factory
| Scenario | Use Case |
|---|---|
| Multiple product families exist (e.g., UI themes, regional configurations) | Ensure all components belong to the same family |
| Client must be independent of how products are created | Promote decoupling |
| System must support swapping entire product families | Runtime configuration |
| Product creation logic is complex and varies per family | Encapsulate creation rules |
Avoid when:
- Only one product type is needed → Use Factory Method
- Products are unrelated → Simple instantiation suffices
Where It Is Used in Real Systems
| Domain | Example |
|---|---|
| GUI Toolkits | Windows vs macOS widgets (buttons, dialogs) |
| Game Development | Weapon systems per era (Medieval, Modern) |
| E-Commerce | Regional payment, tax, shipping, currency |
| Database Drivers | Oracle vs SQL Server connection factories |
| IoT Platforms | Device-specific sensor/actuator families |
Key Benefits
- Consistency: Guarantees compatible objects within a family.
- Extensibility: Add new families without modifying client.
- Open/Closed Principle: Open for extension, closed for modification.
- Testability: Easy to inject mock factories.
Real-World Example: E-Commerce Regional Checkout System
An e-commerce platform operates globally. The checkout process varies by region due to:
- Different payment gateways
- Unique tax rules
- Local shipping providers
- Region-specific currency formatting
We define three product families: US, EU, and India.
Each family includes:
- IPaymentProcessor
- ITaxCalculator
- IShippingProvider
- ICurrencyFormatter
The client (CheckoutService) remains unaware of concrete implementations.
C# Implementation
using System;
// ==================== ABSTRACT PRODUCTS ====================
public interface IPaymentProcessor
{
bool ProcessPayment(decimal amount, string currencyCode);
}
public interface ITaxCalculator
{
decimal CalculateTax(decimal subtotal, string regionCode);
}
public interface IShippingProvider
{
decimal CalculateShipping(decimal weightKg, string destination);
string GetTrackingUrl(string orderId);
}
public interface ICurrencyFormatter
{
string Format(decimal amount);
string CurrencyCode { get; }
}
// ==================== CONCRETE PRODUCTS: US ====================
public class StripeProcessor : IPaymentProcessor
{
public bool ProcessPayment(decimal amount, string currencyCode)
{
Console.WriteLine($"[US] Processing {currencyCode}{amount:F2} via Stripe...");
return true; // Simulate success
}
}
public class SalesTaxCalculator : ITaxCalculator
{
public decimal CalculateTax(decimal subtotal, string regionCode)
{
decimal rate = regionCode == "CA" ? 0.0875m : 0.06m; // Example rates
return subtotal * rate;
}
}
public class FedExProvider : IShippingProvider
{
public decimal CalculateShipping(decimal weightKg, string destination)
=> weightKg * 5.50m;
public string GetTrackingUrl(string orderId)
=> $"https://fedex.com/track/{orderId}";
}
public class USDCurrencyFormatter : ICurrencyFormatter
{
public string Format(decimal amount) => $"${amount:F2}";
public string CurrencyCode => "USD";
}
// ==================== CONCRETE PRODUCTS: EU ====================
public class AdyenProcessor : IPaymentProcessor
{
public bool ProcessPayment(decimal amount, string currencyCode)
{
Console.WriteLine($"[EU] Processing {currencyCode}{amount:F2} via Adyen...");
return true;
}
}
public class VATCalculator : ITaxCalculator
{
public decimal CalculateTax(decimal subtotal, string regionCode)
=> subtotal * 0.20m; // Standard 20% VAT
}
public class DHLProvider : IShippingProvider
{
public decimal CalculateShipping(decimal weightKg, string destination)
=> weightKg * 8.90m;
public string GetTrackingUrl(string orderId)
=> $"https://dhl.com/track/{orderId}";
}
public class EURCurrencyFormatter : ICurrencyFormatter
{
public string Format(decimal amount) => $"€{amount:F2}";
public string CurrencyCode => "EUR";
}
// ==================== CONCRETE PRODUCTS: INDIA ====================
public class RazorpayProcessor : IPaymentProcessor
{
public bool ProcessPayment(decimal amount, string currencyCode)
{
Console.WriteLine($"[IN] Processing {currencyCode}{amount:F2} via Razorpay...");
return true;
}
}
public class GSTCalculator : ITaxCalculator
{
public decimal CalculateTax(decimal subtotal, string regionCode)
=> subtotal * 0.18m; // 18% GST
}
public class DelhiveryProvider : IShippingProvider
{
public decimal CalculateShipping(decimal weightKg, string destination)
=> weightKg * 65.00m;
public string GetTrackingUrl(string orderId)
=> $"https://delhivery.com/track/{orderId}";
}
public class INRCurrencyFormatter : ICurrencyFormatter
{
public string Format(decimal amount) => $"₹{amount:F2}";
public string CurrencyCode => "INR";
}
// ==================== ABSTRACT FACTORY ====================
public interface ICheckoutFactory
{
IPaymentProcessor CreatePaymentProcessor();
ITaxCalculator CreateTaxCalculator();
IShippingProvider CreateShippingProvider();
ICurrencyFormatter CreateCurrencyFormatter();
}
// ==================== CONCRETE FACTORIES ====================
public class USCheckoutFactory : ICheckoutFactory
{
public IPaymentProcessor CreatePaymentProcessor() => new StripeProcessor();
public ITaxCalculator CreateTaxCalculator() => new SalesTaxCalculator();
public IShippingProvider CreateShippingProvider() => new FedExProvider();
public ICurrencyFormatter CreateCurrencyFormatter() => new USDCurrencyFormatter();
}
public class EUCheckoutFactory : ICheckoutFactory
{
public IPaymentProcessor CreatePaymentProcessor() => new AdyenProcessor();
public ITaxCalculator CreateTaxCalculator() => new VATCalculator();
public IShippingProvider CreateShippingProvider() => new DHLProvider();
public ICurrencyFormatter CreateCurrencyFormatter() => new EURCurrencyFormatter();
}
public class INCheckoutFactory : ICheckoutFactory
{
public IPaymentProcessor CreatePaymentProcessor() => new RazorpayProcessor();
public ITaxCalculator CreateTaxCalculator() => new GSTCalculator();
public IShippingProvider CreateShippingProvider() => new DelhiveryProvider();
public ICurrencyFormatter CreateCurrencyFormatter() => new INRCurrencyFormatter();
}
// ==================== CLIENT ====================
public class CheckoutService
{
private readonly IPaymentProcessor _paymentProcessor;
private readonly ITaxCalculator _taxCalculator;
private readonly IShippingProvider _shippingProvider;
private readonly ICurrencyFormatter _currencyFormatter;
public CheckoutService(ICheckoutFactory factory)
{
_paymentProcessor = factory.CreatePaymentProcessor();
_taxCalculator = factory.CreateTaxCalculator();
_shippingProvider = factory.CreateShippingProvider();
_currencyFormatter = factory.CreateCurrencyFormatter();
}
public void ProcessCheckout(decimal subtotal, decimal weightKg, string regionCode, string orderId)
{
decimal tax = _taxCalculator.CalculateTax(subtotal, regionCode);
decimal shipping = _shippingProvider.CalculateShipping(weightKg, regionCode);
decimal total = subtotal + tax + shipping;
string formattedSubtotal = _currencyFormatter.Format(subtotal);
string formattedTax = _currencyFormatter.Format(tax);
string formattedShipping = _currencyFormatter.Format(shipping);
string formattedTotal = _currencyFormatter.Format(total);
Console.WriteLine("=== Checkout Summary ===");
Console.WriteLine($"Subtotal: {formattedSubtotal}");
Console.WriteLine($"Tax: {formattedTax}");
Console.WriteLine($"Shipping: {formattedShipping}");
Console.WriteLine($"Total: {formattedTotal}");
bool paid = _paymentProcessor.ProcessPayment(total, _currencyFormatter.CurrencyCode);
if (paid)
{
Console.WriteLine($"Payment successful. Tracking: {_shippingProvider.GetTrackingUrl(orderId)}");
}
}
}
// ==================== FACTORY PROVIDER ====================
public static class CheckoutFactoryProvider
{
public static ICheckoutFactory GetFactory(string region)
{
return region.ToUpper() switch
{
"US" => new USCheckoutFactory(),
"EU" => new EUCheckoutFactory(),
"IN" => new INCheckoutFactory(),
_ => throw new NotSupportedException($"Region '{region}' is not supported.")
};
}
}
// ==================== DEMO ====================
class Program
{
static void Main()
{
Console.WriteLine("E-COMMERCE CHECKOUT USING ABSTRACT FACTORY\n");
// US Checkout
var usCheckout = new CheckoutService(CheckoutFactoryProvider.GetFactory("US"));
usCheckout.ProcessCheckout(100.00m, 2.5m, "CA", "ORD-1001");
Console.WriteLine();
// EU Checkout
var euCheckout = new CheckoutService(CheckoutFactoryProvider.GetFactory("EU"));
euCheckout.ProcessCheckout(100.00m, 2.5m, "DE", "ORD-1002");
Console.WriteLine();
// India Checkout
var inCheckout = new CheckoutService(CheckoutFactoryProvider.GetFactory("IN"));
inCheckout.ProcessCheckout(1000.00m, 1.0m, "MH", "ORD-1003");
}
}Sample Output
E-COMMERCE CHECKOUT USING ABSTRACT FACTORY
=== Checkout Summary ===
Subtotal: $100.00
Tax: $8.75
Shipping: $13.75
Total: $122.50
[US] Processing USD122.50 via Stripe...
Payment successful. Tracking: https://fedex.com/track/ORD-1001
=== Checkout Summary ===
Subtotal: €100.00
Tax: €20.00
Shipping: €22.25
Total: €142.25
[EU] Processing EUR142.25 via Adyen...
Payment successful. Tracking: https://dhl.com/track/ORD-1002
=== Checkout Summary ===
Subtotal: ₹1000.00
Tax: ₹180.00
Shipping: ₹65.00
Total: ₹1245.00
[IN] Processing INR1245.00 via Razorpay...
Payment successful. Tracking: https://delhivery.com/track/ORD-1003UML Class Diagram

Participants in the Abstract Factory Pattern
The classes and objects participating in this pattern include:
- AbstractFactory (ICheckoutFactory)
- Declares an interface for operations that create abstract product objects.
- ConcreteFactory (USCheckoutFactory, EUCheckoutFactory, INCheckoutFactory)
- Implements the operations to create concrete product objects.
- AbstractProduct (IPaymentProcessor, ITaxCalculator, IShippingProvider, ICurrencyFormatter)
- Declares an interface for a type of product object.
- Product (StripeProcessor, AdyenProcessor, RazorpayProcessor, SalesTaxCalculator, VATCalculator, etc.)
- Defines a product object to be created by the corresponding concrete factory.
- Implements the AbstractProduct interface.
- Client (CheckoutService)
- Uses only interfaces declared by AbstractFactory and AbstractProduct classes.
Summary
| Element | Role in E-Commerce Example |
|---|---|
| AbstractFactory | ICheckoutFactory defines contract for creating regional services |
| ConcreteFactory | USCheckoutFactory, EUCheckoutFactory, INCheckoutFactory |
| AbstractProduct | Interfaces for payment, tax, shipping, currency |
| Product | Concrete implementations per region |
| Client | CheckoutService — works with abstractions only |
The Abstract Factory pattern ensures regional consistency, global scalability, and clean separation of concerns — making it a cornerstone of enterprise e-commerce architectures.




