DEV Community

Rohit Cdy
Rohit Cdy

Posted on

Factory Method Design Pattern in C#

Factory Method Design Pattern
Introduction

The Factory Method Design Pattern is a creational design pattern that allows us to create objects without exposing the creation logic to the client. It provides a way to create objects based on input parameters and returns them using a common interface.

Real-Time Example
Suppose we’re building an application to display Credit Card Details. We have three credit card classes: MoneyBack, Titanium, and Platinum, all of which are subclasses of the CreditCard superclass (or super interface). Each credit card class implements methods like GetCardType, GetCreditLimit, and GetAnnualCharge.

Our task is to ask the user to select a credit card type. Based on their choice, we need to display relevant information about the selected credit card.

Example Without Using the Factory Pattern
Let’s first see how we might approach this without using the Factory Design Pattern:

// Without Factory Pattern
class Program
{
    static void Main()
    {
        // User selects a credit card type (e.g., "MoneyBack")
        string userChoice = GetUserInput();

        // Create an instance based on user choice
        CreditCard card;
        if (userChoice == "MoneyBack")
            card = new MoneyBack();
        else if (userChoice == "Titanium")
            card = new Titanium();
        else if (userChoice == "Platinum")
            card = new Platinum();
        else
            throw new ArgumentException("Invalid choice");

        // Display credit card details
        Console.WriteLine($"Card Type: {card.GetCardType()}");
        Console.WriteLine($"Credit Limit: {card.GetCreditLimit()}");
        Console.WriteLine($"Annual Charge: {card.GetAnnualCharge()}");
    }

    // Other methods...
}

Enter fullscreen mode Exit fullscreen mode

Problems Without Factory Pattern
Tight Coupling: The client code is tightly coupled to specific credit card classes.
Maintenance Challenges: Adding new credit card types requires modifying the client code.
Testing Complexity: Unit testing becomes difficult due to direct dependencies on concrete classes.

Implementing the Factory Design Pattern
Now let’s use the Factory Design Pattern to address these issues:

// With Factory Pattern
class Program
{
    static void Main()
    {
        // User selects a credit card type (e.g., "MoneyBack")
        string userChoice = GetUserInput();

        // Create a credit card factory
        CreditCardFactory factory = new CreditCardFactory();

        // Get the appropriate credit card object
        CreditCard card = factory.CreateCreditCard(userChoice);

        // Display credit card details
        Console.WriteLine($"Card Type: {card.GetCardType()}");
        Console.WriteLine($"Credit Limit: {card.GetCreditLimit()}");
        Console.WriteLine($"Annual Charge: {card.GetAnnualCharge()}");
    }

    // Other methods...
}

// Factory class
class CreditCardFactory
{
    public CreditCard CreateCreditCard(string type)
    {
        switch (type)
        {
            case "MoneyBack":
                return new MoneyBack();
            case "Titanium":
                return new Titanium();
            case "Platinum":
                return new Platinum();
            default:
                throw new ArgumentException("Invalid choice");
        }
    }
}

// Credit card superclass
interface CreditCard
{
    string GetCardType();
    decimal GetCreditLimit();
    decimal GetAnnualCharge();
}

// Concrete credit card classes
class MoneyBack : CreditCard { /* Implementation */ }
class Titanium : CreditCard { /* Implementation */ }
class Platinum : CreditCard { /* Implementation */ }

Enter fullscreen mode Exit fullscreen mode

Summary
The Factory Design Pattern provides flexibility, separation of concerns, and better maintainability. It allows us to create objects dynamically based on input parameters, without exposing the creation logic to the client. Choose the Factory Pattern when you need to create objects with varying behavior or when you want to promote loose coupling between client code and concrete classes

Top comments (0)