Isaac.

Design Patterns: Factory

Learn the Factory pattern: decouple object creation from usage.

By EMEPublished: February 20, 2025
design patternsfactorycreational patternsobject creation

A Simple Analogy

A car factory doesn't sell different car models; it manufactures them. When you order a car, you specify the type (sedan, SUV), and the factory produces it. The Factory pattern works the same way: classes delegate object creation to a factory instead of directly instantiating types.


What Is the Factory Pattern?

Factory is a creational design pattern that provides an interface for creating objects without specifying their concrete classes. It hides instantiation logic and promotes flexibility.


Why Use Factory?

  • Decouple creation from usage: Code doesn't depend on concrete classes
  • Flexibility: Add new types without changing client code
  • Centralized logic: Object creation logic in one place
  • Easy testing: Mock factories for unit tests

Structure

Factory Interface/Class
  └─ Create(type): Object

ConcreteFactory
  └─ Create(type) returns ConcreteProduct

Product Interface
  └─ DoSomething()

ConcreteProduct A, B, C
  └─ DoSomething() implementations

Simple Factory Example

public interface INotifier
{
    void Send(string message);
}

public class EmailNotifier : INotifier
{
    public void Send(string message) => Console.WriteLine($"Email: {message}");
}

public class SmsNotifier : INotifier
{
    public void Send(string message) => Console.WriteLine($"SMS: {message}");
}

public class NotifierFactory
{
    public static INotifier Create(string type) => type switch
    {
        "email" => new EmailNotifier(),
        "sms" => new SmsNotifier(),
        _ => throw new ArgumentException("Unknown type")
    };
}

// Usage
var notifier = NotifierFactory.Create("email");
notifier.Send("Hello!");  // Email: Hello!

Abstract Factory Example

// Payment processor family
public interface IPaymentProcessor
{
    void Process(decimal amount);
}

public interface IPaymentFactory
{
    IPaymentProcessor CreateProcessor();
}

public class CreditCardFactory : IPaymentFactory
{
    public IPaymentProcessor CreateProcessor() => new CreditCardProcessor();
}

public class PayPalFactory : IPaymentFactory
{
    public IPaymentProcessor CreateProcessor() => new PayPalProcessor();
}

// Client code
public class CheckoutService
{
    private readonly IPaymentFactory _factory;
    
    public CheckoutService(IPaymentFactory factory) => _factory = factory;
    
    public void Checkout(decimal amount)
    {
        var processor = _factory.CreateProcessor();
        processor.Process(amount);
    }
}

Real-World Use Cases

  • Logging frameworks: Logger factories create logger instances
  • Database connections: Connection factories manage DB instances
  • UI frameworks: Widget factories create different UI components
  • Dependency injection containers: Factories resolve dependencies
  • Payment gateways: Processor factories for different payment methods

Related Concepts to Explore

  • Abstract Factory pattern
  • Builder pattern (for complex objects)
  • Singleton pattern (often paired with Factory)
  • Dependency injection

Summary

The Factory pattern centralizes object creation, promoting flexibility and decoupling. Use it when object creation is complex, types vary, or you want to control instantiation logic in one place.