Factory Pattern

September 11, 2017

I recently introduced a new blog series that I am starting aimed at helping beginners understand software patterns.  If you didn’t catch that post, you can read it here.  The first pattern I want to tackle is the factory pattern.  There are lots of great articles out there discussing these patterns in depth, but I want to take a different approach to them.  I want to look at them from a simple perspective.

When you think of a factory, what comes to mind?  In my mind’s eye, I see images of big brick buildings billowing out clouds of dark smoke all with the purpose of producing thousands and thousands of widgets.  The factory pattern is much like the brick building of my imagination in that it has only one purpose.  Its sole responsibility is to create objects.

The idea behind the factory pattern is pretty simple.  You have some code that needs some other code as a dependency.  There may be multiple objects that could satisfy the needs of your code depending on the circumstance.  You program your dependent code to utilize an interface rather than creating a new object.  You then write classes that implement the interface.

Let’s create a very simple example to illustrate the point.  Let’s create a simple console application that has only a line of code to write the phrase Hello World out to the console and another to pause execution until we hit enter.

using System;

namespace FactoryExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }
    }
}

Now suppose we want to be able to change the greeting based on some criteria. Instead of writing Hello World, we want our greeting to be written out by an object that specializes in the type of greeting we need. To do this, we need to write a class that returns the greeting to write.

using System;

namespace FactoryExample
{
    class MorningGreeting
    {
        public string GetGreeting()
        {
            return "Good Morning!";
        }
    }
}

We also have to modify our Program.cs class to use the new object for our greeting.

using System;

namespace FactoryExample
{
    class Program
    {
        static void Main(string[] args)
        {
            MorningGreeting greeting = new MorningGreeting();
            Console.WriteLine(greeting.GetGreeting());
            Console.ReadLine();
        }
    }
}

If you notice above, we instantiate the MorningGreeting object and then use it to get the message that we want to display. The problem is that we are now tightly coupled between our MorningGreeting class and the code that calls it. We don’t want the application to display “Good Morning” all day long. We want to use something different depending on the time of day. We need another class to display “Good Afternoon” to the user when it is past 12 pm. Let’s write that class.

using System;

namespace FactoryExample
{
    class AfternoonGreeting
    {
        public string GetGreeting()
        {
            return "Good Afternoon!";
        }
    }
}

We now have an issue though. In order to use the AfternoonGreeting class the way it is setup in our Program.cs class, we would have to modify the line of code that instantiates our greeting object and then recompile our application. This simply isn’t feasible. We need to have a way to “de-couple” our code and select which object should be used in a given circumstance. To do this, we need to create an Interface. Interfaces allow us to write similar classes that provide the same methods (with the same parameters and return types) in different classes that can then be used interchangeably. Let’s create an interface that would allow us to do this with our greeting classes.

using System;

namespace FactoryExample
{
    interface IGreeting
    {
        string GetGreeting();
    }
}

We then have to modify each of our greeting classes to implement the interface. We do this by using a colon and the name of the interface following the class declaration.

using System;

namespace FactoryExample
{
    class MorningGreeting : IGreeting
    {
        public string GetGreeting()
        {
            return "Good Morning!";
        }
    }
}
using System;

namespace FactoryExample
{
    class AfternoonGreeting : IGreeting
    {
        public string GetGreeting()
        {
            return "Good Afternoon!";
        }
    }
}

Now we can go back to our Program.cs class and modify it to use the IGreeting interface instead of a concrete class as it’s greeting variable type. This will allow for any class that implements the IGreeting interface to be used there.

using System;

namespace FactoryExample
{
    class Program
    {
        static void Main(string[] args)
        {
            IGreeting greeting = new MorningGreeting();
            Console.WriteLine(greeting.GetGreeting());
            Console.ReadLine();
        }
    }
}

There is still a problem though. We created the interface to allow us to use any class that implements that interface to be used. We also coded our logic to use the interface rather than a concrete implementation by specifying the type of our greeting variable to be IGreeting. We are still instantiating a concrete implementation though by specifying that the greeting variable is = new MorningGreeting. We want to let the system choose which object to use based on the time of day. This is where our factory comes in. To create our factory, let’s add another class. I’m going to make this one static.

using System;

namespace FactoryExample
{
    static class GreetingFactory
    {
        public static IGreeting CreateGreeting()
        {
            DateTime noon = Convert.ToDateTime("12:00:00 PM");
            DateTime now = DateTime.Now;

            if (now < noon)
            {
                return new MorningGreeting();
            }
            return new AfternoonGreeting();
        }
    }
}

This gives us a class and method that allow us to get the correct object based on some criteria. In our case is it morning or afternoon. We now only need to modify our Program.cs class one more time to use the factory to give us whichever object is appropriate.

using System;

namespace FactoryExample
{
    class Program
    {
        static void Main(string[] args)
        {
            IGreeting greeting = GreetingFactory.CreateGreeting();
            Console.WriteLine(greeting.GetGreeting());
            Console.ReadLine();
        }
    }
}

That should do it. If we run our application at different times of day you should find that the greeting changes depending on whether it is before or after noon. There are easier ways to accomplish what we just did, but think about how this pattern could be used for more complex scenarios. Maybe an insurance company needs to implement a set of rules for calculating a rate based on which state they are selling a policy in. We could create and return the proper rate engine object for the state. Anytime you may want to switch which implementation of an object you need at runtime based on specific criteria, a factory is a reasonable choice to consider.

Modern applications use fewer factories and rely more on dependency injection (DI) for this type of functionality, but understanding factories is a great step toward understanding how DI works.

Comments are closed.

DevCoaches © 2016 - 2017