The Factory Design Pattern in C#

The factory design pattern is a widely accepted and well-regarded creational design pattern. It is one of the original 23 design patterns from the Gang of Four (GoF). The factory design pattern defines an interface for creating new objects instead of using the new keyword but allows classes that implement the interface to decide which class to instantiate. Simply put, the factory design pattern allows instantiation of new classes to be deferred until runtime.

 

What problem does it solve?

The factory design pattern really shines when used to farm out the creation of complex objects or replace code that is complex because of the many different types of objects that can be created. For example, if we are creating one of five different objects based on the value of a parameter, there would most likely be a case statement in place to test the possible values of that parameter and instantiate the correct class. This logic could easily be moved to the factory. Then, adding five more possibilities would not be such a large problem because the factory is in place and the only real change would be in the creation method.

For this demo, I want to create a factory that will give me a country object based on the name that I type in.

The Actors

Factory

An abstract class that defines the signature of the concrete factory.

Listing 1.1 – CountryFactory.cs

public abstract class CountryFactory
{
    public abstract ICountry CreateCountry(string countryName);
}

Concrete Factory

A class that implements the abstract factory signatures and handles the creation of objects.

Listing 1.2 – ConcreteCountryFactory.cs

public class ConcreteCountryFactory : CountryFactory
{
    public override ICountry CreateCountry(string countryName)
    {
        ICountry country = null;

        switch(countryName.ToLower())
        {
            case "brazil":
                country = new Brazil();
                break;
            case "canada":
                country = new Canada();
                break;
            case "china":
                country = new China();
                break;
            case "france":
                country = new France();
                break;
            case "india":
                country = new India();
                break;
            case "mexico":
                country = new Mexico();
                break;
            case "uk":
                country = new UnitedKingdom();
                break;
            case "usa":
                country = new UnitedStates();
                break;                    
        }

        return country;
    }
}

ICountry

An interface that defines the signature that all possible countries will be created by the concrete factory must adhere to.

Listing 1.3 – ICountry.cs

public interface ICountry
{
    string Name { get; }
    string GetLanguage();
}

Country n

Any number of objects that will be created by the concrete factory that adhere to the ICountry interface.

Listing 1.4 – Sample Countries

public class Brazil : ICountry
{
    public string Name
    {
        get
        {
            return "Brazil";
        }
    }

    public string GetLanguage()
    {
        return "Portuguese";
    }
}

public class France : ICountry
{
    public string Name
    {
        get
        {
            return "France";
        }
    }

    public string GetLanguage()
    {
        return "French";
    }
}

public class UnitedStates : ICountry
{
    public string Name
    {
        get
        {
            return "USA";
        }
    }

    public string GetLanguage()
    {
        return "English";
    }
}

How to implement

I created a simple console application that hands off control to the SampleDemo class listed below. The important thing is to create your factory.

Listing 1.6 – SampleDemo.cs

public class SampleDemo
{
    private CountryFactory _factory = null;

    public SampleDemo()
    {
        _factory = new ConcreteCountryFactory();
    }

    public void Run()
    {
        while (1 > 0)
        {
            Console.WriteLine("Enter the name of a country");

            string countryName = Console.ReadLine();

            if(countryName == "exit")
            {
                return;
            }

            ICountry country = _factory.CreateCountry(countryName);

            Console.WriteLine($"The official or dominant language of {country.Name} is {country.GetLanguage()}.");
        }
    }
}

Conclusion

The Factory Design Pattern, like other design patterns, is another tool in your belt and when properly implemented, can make your software simpler to write and easier to maintain. This implementation, while simplistic, is easy to extend to other object types.

Leave a Reply

Your email address will not be published.