Factory Method Design Pattern in C#

Factory Method Design Pattern in C# with an Example

In this article, I am going to discuss the Factory Method Design Pattern in C# with an example. Please read our previous article before proceeding to this article where we discussed the Simple Factory Design Pattern in C# with an example. The Factory Method Design Pattern belongs to the Creational Pattern category which means it is used to simplify the process of object creation.

Note: The most important point that you need to keep in mind is the Factory method design pattern is not the same as the simply Factory design pattern that we discussed in our previous article. Most of the people think that both are the same and thus they use the terms Factory and Factory method interchangeably which is not right.

What is Factory Method Design Pattern in C#?

According to Gang of Four Definition “Define an interface for creating an object, but let the sub-classes to decide which class to instantiate. The Factory method lets a class defer instantiation it uses to sub-classes”.

That means the factory method design pattern in C# abstract the process of object creation logic to the client and allows the object to be created at run-time when it is required.

Let us simplify this definition. The Factory Method Design Pattern in C# is used, when we need to create the object (i.e. instance of the Product class) without exposing the object creation logic to the client. To achieve this, here, in factory method design pattern, we need to create an abstract class as the Factory class which will create and return the instance of the product, but it will let the subclasses to decide which class to instantiate. That means the subclasses of the abstract class will decide which product class object needs to be created which is shown in the following image

Factory Method Design Pattern in C#

If this is not clear at the moment don’t worry, let us try to understand this with an example.

Example: Factory Method Design Pattern in C#:

We are going to develop an application for showing the credit card details. We have three types of credit card such as MoneyBack, Titanium, and Platinum. So based on the credit card the user selected, we need to display the information such as the type of the credit, limit of the credit card and the annual charges of the credit card.

Creating Product Interface and Concrete Classes:

Create an interface with the name ICreditCard and then copy and paste the following code. This is going to be our Product interface which will provide the signature of the common functionalities which should be implemented by the concrete product classes.

public interface ICreditCard
{
    string GetCardType();
    int GetCreditLimit();
    int GetAnnualCharge();
}

As we have three types of Credit cards in our example, so we are going to create three classes (MoneyBackCreditCard, TitaniumCreditCard, and PlatinumCreditCard) by implementing the ICreditCard interface as shown below.

//Concrete Product 1
public class MoneyBackCreditCard : ICreditCard
{
    public string GetCardType()
    {
        return "MoneyBack";
    }

    public int GetCreditLimit()
    {
        return 15000;
    }

    public int GetAnnualCharge()
    {
        return 500;
    }
}

//Concrete Product 2
public class TitaniumCreditCard : ICreditCard
{
    public string GetCardType()
    {
        return "Titanium";
    }

    public int GetCreditLimit()
    {
        return 25000;
    }

    public int GetAnnualCharge()
    {
        return 1500;
    }
}

//Concrete Product 3
public class PlatinumCreditCard : ICreditCard
{
    public string GetCardType()
    {
        return "Platinum";
    }

    public int GetCreditLimit()
    {
        return 35000;
    }

    public int GetAnnualCharge()
    {
        return 2000;
    }
}

As you can see all the above three classes implements all the methods of the ICreditCard interface with their own logic.

Creating the Factory Class and its sub classes:

As per the definition, we need to create an abstract class or interface for creating the object. So, let us create an abstract class which will be our factory class with a public exposed method. That method is nothing but the factory method which will return the instance of the product. So create a class file with the name and then copy and paste the following code in it.

public abstract class CreditCardAbstractFactory
{
    //This method is going to be implemented by the sub classes
    protected abstract ICreditCard MakeProduct();
    public ICreditCard CreateProduct()
    {
        return this.MakeProduct();
    }
}

We created the above abstract class with one abstract method i.e. MakeProduct() and one concrete method i.e. CreateProduct(). The CreateProduct() method internally calls the MakeProduct() method of the subclass which will create the product instance and return that instance.

So let us create the sub classes of the above abstract class. As we have three types of CreditCard, so we are going to create three classes (PlatinumCreditCardFactory, MoneyBackCreditCardFactory, and TitaniumCreditCardFactory) which will implement the above abstract class.

public class PlatinumCreditCardFactory : CreditCardAbstractFactory
{
    protected override ICreditCard MakeProduct()
    {
        ICreditCard product = new PlatinumCreditCard();

        //Do something with the object once you get the object. 
        return product;
    }
}

public class MoneyBackCreditCardFactory : CreditCardAbstractFactory
{
    protected override ICreditCard MakeProduct()
    {
        ICreditCard product = new MoneyBackCreditCard();

        //Do something with the object once you get the object. 
        return product;
    }
}

public class TitaniumCreditCardFactory : CreditCardAbstractFactory
{
    protected override ICreditCard MakeProduct()
    {
        ICreditCard product = new TitaniumCreditCard();

        //Do something with the object once you get the object. 
        return product;
    }
}

As you can see the above three classes implement the MakeProduct method of the CreditCardAbstractFactory class. That’s it. We are done with our implementation.

Let’s compare the Gang of Four Definition with our example. According to Gang of Four, we need to define an interface or abstract class for creating an object. In our example, it is an abstract class i.e. CreditCardAbstractFactory class. The second part of the definition saying that let the sub-classes to decide which class to instantiate. In our example, the subclasses are PlatinumCreditCardFactory, MoneyBackCreditCardFactory, and TitaniumCreditCardFactory. So these sub classes will decide which class to instantiate, for example, MoneyBackCreditCard, TitaniumCreditCard, and PlatinumCreditCard.

Consuming the factory Method in the Client Code:

If you want to create an instance of the PlatinumCreditCard then call the CreateProduct method of the PlatinumCreditCardFactory instance, similarly, if you want the instance of TitaniumCreditCard, then call the CreateProduct method of the TitaniumCreditCardFactory instance. So modify the Main method of the program class as shown below.

public class Program
{
    static void Main(string[] args)
    {
        //This is going to return an instance of a Particular Card type object 
        //through the interface ICreditCard
        ICreditCard CreditCardInstance = new PlatinumCreditCardFactory().CreateProduct();

        if (CreditCardInstance != null)
        {
            Console.WriteLine("CardType : " + CreditCardInstance.GetCardType());
            Console.WriteLine("CreditLimit : " + CreditCardInstance.GetCreditLimit());
            Console.WriteLine("AnnualCharge :" + CreditCardInstance.GetAnnualCharge());
        }
        else
        {
            Console.Write("Invalid Card Type");
        }

        Console.WriteLine("--------------");
        CreditCardInstance = new MoneyBackCreditCardFactory().CreateProduct();

        if (CreditCardInstance != null)
        {
            Console.WriteLine("CardType : " + CreditCardInstance.GetCardType());
            Console.WriteLine("CreditLimit : " + CreditCardInstance.GetCreditLimit());
            Console.WriteLine("AnnualCharge :" + CreditCardInstance.GetAnnualCharge());
        }
        else
        {
            Console.Write("Invalid Card Type");
        }

        Console.ReadLine();
    }
}

When we run the application, it displays the output as expected as shown below.

Providing another layer of Abstraction:

In the above example, we directly call the CreateProduct method on a particular factory class instance to get the actual product instance. What if I need to create the product instance based on the card type value that I received from the user. If this is your requirement, then you need to create another simple factory class as shown below. Create a class with the name CreditCardFactory and then copy and paste the following code.

public class CreditCardFactory
{
    public ICreditCard CreateObject(int CreditCardType)
    {
        ICreditCard product = null;

        if (CreditCardType == 1)
        {
            product = new PlatinumCreditCardFactory().CreateProduct();
        }
        else if (CreditCardType == 2)
        {
            product = new MoneyBackCreditCardFactory().CreateProduct();
        }
        else if (CreditCardType == 3)
        {
            product = new TitaniumCreditCardFactory().CreateProduct();
        }

        return product;
    }
}

The above code is very straightforward. Based on the CreditCardType value, it will create the appropriate concrete factory instance and then call the CreateProduct method which will return the appropriate product instance.

Modify the Main method:

Now, in order to get the appropriate product instance based on the CreditCardType value, modify the Main method of the Program class as shown below.

public class Program
{
    static void Main(string[] args)
    {
        //Setting the Card Type value 
        int CreditCardType = 1;

        //This is going to return an instance of a Particular Card type object 
        var CreditCardInstance = new CreditCardFactory().CreateObject(CreditCardType);

        if (CreditCardInstance != null)
        {
            Console.WriteLine("CardType : " + CreditCardInstance.GetCardType());
            Console.WriteLine("CreditLimit : " + CreditCardInstance.GetCreditLimit());
            Console.WriteLine("AnnualCharge :" + CreditCardInstance.GetAnnualCharge());
        }
        else
        {
            Console.Write("Invalid Card Type");
        }

        Console.ReadLine();
    }
}

Now run the application and you will see everything is working as expected. In the next article, I am going to discuss the Abstract Factory Design Pattern in C# with an example.

SUMMARY

In this article, I try to explain the Factory Method Design Pattern in C# step by step with an example. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *