C#  

Factory Pattern C#

Introduction

The Factory Pattern is a creational design pattern that provides an interface for creating objects while allowing subclasses or a centralized factory to decide which concrete class to instantiate. It promotes loose coupling by eliminating direct object creation using the new keyword in client code.

Problem Statement

When an application directly creates objects using concrete classes, it becomes tightly coupled to those implementations. This makes the system hard to extend, test, and maintain, especially when new object types are introduced.

Solution

The Factory Pattern encapsulates object creation logic in a separate factory class or method. The client requests an object from the factory by providing some input, and the factory returns the appropriate concrete implementation.

Key Benefits

Reduces tight coupling between client and concrete classes
Centralizes object creation logic
Improves maintainability and scalability
Supports Open Closed Principle

Types of Factory Pattern

Simple Factory
Factory Method
Abstract Factory

This article focuses on the Simple Factory pattern, which is widely used in real-world applications.

Example Scenario

Assume we are building a notification system that can send Email, SMS, or Push notifications. The client should not know which concrete class is being instantiated.

Step 1 Define the Product Interface

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

Step 2 Create Concrete Products

public class EmailNotification : INotification
{
    public void Send(string message)
    {
        Console.WriteLine("Email sent: " + message);
    }
}

public class SmsNotification : INotification
{
    public void Send(string message)
    {
        Console.WriteLine("SMS sent: " + message);
    }
}

public class PushNotification : INotification
{
    public void Send(string message)
    {
        Console.WriteLine("Push notification sent: " + message);
    }
}

Step 3 Create the Factory Class

public static class NotificationFactory
{
    public static INotification Create(string type)
    {
        return type.ToLower() switch
        {
            "email" => new EmailNotification(),
            "sms" => new SmsNotification(),
            "push" => new PushNotification(),
            _ => throw new ArgumentException("Invalid notification type")
        };
    }
}

Step 4 Client Usage

class Program
{
    static void Main()
    {
        INotification notification = NotificationFactory.Create("email");
        notification.Send("Factory Pattern in action");
    }
}

How It Works

The client calls the factory instead of instantiating concrete classes directly. The factory evaluates the input and returns the correct implementation of the interface. The client only depends on the abstraction, not the concrete types.

When to Use Factory Pattern

When object creation logic is complex
When the exact type of object is determined at runtime
When you want to decouple object creation from usage
When adding new types should not affect client code

Common Mistakes

Overusing factory for simple object creation
Adding too much logic inside the factory
Violating single responsibility by mixing business logic in factory

Real World Usage

Dependency Injection containers internally use factory concepts
ORM frameworks create database providers using factories
Logging frameworks instantiate loggers based on configuration

Conclusion

The Factory Pattern is a foundational design pattern that helps build flexible and maintainable systems. By centralizing object creation and programming to interfaces, applications become easier to extend and test without modifying existing client code.