Factory Design Pattern
Simplify Object Creation in C# with the Factory Design Pattern
The Factory Design Pattern is a creational pattern that provides a way to create objects without specifying the exact class.
Creating objects in a flexible and maintainable way is a common challenge in software development. The Factory Design Pattern solves this problem by allowing you to create objects without specifying their exact classes. Instead, you ask a factory to provide the object you need.
Use Case: Payment Processing System
Let’s imagine a Payment Processing System:
Your system can accept different payment types: Credit Card, PayPal, or Bkash (mobile payment in Bangladesh).
You don’t want your code to directly depend on specific payment implementations.
When a user chooses a payment method, your system should create the correct payment processor dynamically.
This is a perfect use case for the Factory Pattern.
Step 1: Define the Interface
public interface IPaymentProcessor
{
void ProcessPayment(decimal amount);
}
Step 2: Create Concrete Implementations
public class CreditCardPaymentProcessor : IPaymentProcessor
{
public void ProcessPayment(decimal amount)
{
Console.WriteLine($"Processing credit card payment of {amount:C}");
}
}
public class PayPalPaymentProcessor : IPaymentProcessor
{
public void ProcessPayment(decimal amount)
{
Console.WriteLine($"Processing PayPal payment of {amount:C}");
}
}
public class BkashPaymentProcessor : IPaymentProcessor
{
public void ProcessPayment(decimal amount)
{
Console.WriteLine($"Processing Bkash payment of {amount:C}");
}
}
Step 3: Create the Factory
public static class PaymentFactory
{
public static IPaymentProcessor GetPaymentProcessor(string paymentType)
{
return paymentType.ToLower() switch
{
"creditcard" => new CreditCardPaymentProcessor(),
"paypal" => new PayPalPaymentProcessor(),
"bkash" => new BkashPaymentProcessor(),
_ => throw new ArgumentException("Invalid payment type"),
};
}
}
Step 4: Use the Factory
string paymentType = "CreditCard";
decimal amount = 150.00m;
IPaymentProcessor paymentProcessor = PaymentFactory.GetPaymentProcessor(paymentType);
paymentProcessor.ProcessPayment(amount);
Why the Factory Pattern Matters
Using the Factory Pattern provides several benefits:
Loose Coupling: Your code doesn’t depend on concrete implementations.
Scalability: Easily add new types without changing existing code.
Cleaner Code: Separates object creation logic from business logic.
Dynamic Object Creation: Create objects at runtime based on user input, configuration, or conditions.
Common Use Cases of the Factory Pattern
The Factory Design Pattern is extremely versatile and can be applied in many real-world scenarios. Some of the most common use cases include:
Payment Processing Systems: Dynamically create processors for different payment methods like Credit Card, PayPal, or Mobile Payments, ensuring your code is flexible and maintainable.
Notification Services: Choose the appropriate channel at runtime, whether it’s Email, SMS, or Push Notification, without hardcoding each type.
Database Connections: Switch between multiple database types like SQL Server, MySQL, or MongoDB dynamically, keeping your data access layer decoupled from specific implementations.
Logging Frameworks: Decide at runtime whether to log messages to the Console, File, or Cloud, providing flexibility for different environments.
Document Generation Systems: Produce documents in various formats like PDF, Word, or Excel based on user preferences or system requirements.
Think of the Factory Design Pattern as a object generator: you request the type of object you need, and the factory handles creating it for you. This approach keeps your code organized, flexible, and easy to maintain by separating object creation from your main application logic.