The Factory method is a creational design pattern that provides an interface for creating objects without specifying their concrete classes. It defines a method that we can use to create an object instead of using its constructor. The important thing is that the subclasses can override this method and create objects of different types.

Factory design pattern diagram

In this article, we are going to show you how to implement a Factory method design pattern. Furthermore, we are going to learn how to use the Factory method refactoring technique to hide the constructor and use our own method to expose it.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

We are going to start with the simple factory implementation, and we’re gradually going to improve to achieve a very usable, but readable factory for our objects.

To download the source code for the video, visit our Patreon page (YouTube Patron tier).

For the main page of this series check out C# Design Patterns.


VIDEO: Factory Design Pattern in C#.


Factory Method Implementation

To implement a Factory method pattern, we are going to create a simple Air conditioner application. Our app will receive an input from a user and based on that input will trigger a required action (cooling or warming the room). So let’s start with an interface:

public interface IAirConditioner
{
    void Operate();
}

Now, we need concrete classes to implement this interface:

public class CoolingManager : IAirConditioner
{
    private readonly double _temperature;

    public CoolingManager(double temperature)
    {
        _temperature = temperature;
    }

    public void Operate()
    {
        Console.WriteLine($"Cooling the room to the required temperature of {_temperature} degrees");
    }
}
public class WarmingManager : IAirConditioner
{
    private readonly double _temperature;

    public WarmingManager(double temperature)
    {
        _temperature = temperature;
    }

    public void Operate()
    {
        Console.WriteLine($"Warming the room to the required temperature of {_temperature} degrees.");
    }
}

Great. We have prepared our base functionality. Now let’s create a factory creator for these objects.

Factory Classes

We are going to start with the AirConditionerFactory abstract class:

public abstract class AirConditionerFactory
{
    public abstract IAirConditioner Create(double temperature);
}

This abstract class provides an interface for object creation in derived classes. That being said, let’s implement our concrete creator classes:

public class CoolingFactory : AirConditionerFactory
{
    public override IAirConditioner Create(double temperature) => new CoolingManager(temperature);
}
public class WarmingFactory : AirConditionerFactory
{
    public override IAirConditioner Create(double temperature) => new WarmingManager(temperature);
}

Excellent. Now we are ready to start using our Factory methods. In many examples, we can see the switch statement which switches through the user’s input and selects the required factory class.

That works just fine.

But imagine if we have a lot of factory classes, which is quite common in large projects. That would lead to a quite big switch case statement which is quite unreadable. Therefore, we are going to use another approach.

Factory Execution

Let’s start with a simple enumeration to define air conditioner actions:

public enum Actions
{
    Cooling,
    Warming
}

To continue on, we are going to create the AirConditioner class where the user can specify the type of action and execute the appropriate factory. Our concrete factories inherit from the abstract class and we are going to use that structure in our further implementation:

public class AirConditioner
{
    private readonly Dictionary<Actions, AirConditionerFactory> _factories;

    public AirConditioner()
    {
        _factories = new Dictionary<Actions, AirConditionerFactory>
        {
            { Actions.Cooling, new CoolingFactory() },
            { Actions.Warming, new WarmingFactory() }
        };
    }
}

This is a better way of implementing our factory execution than using a switch-case statement. But we can do it in another more dynamic way, where we don’t have to manually add action and factory creator for each action. Let’s introduce reflection into our project:

public class AirConditioner
{
    private readonly Dictionary<Actions, AirConditionerFactory> _factories;

    public AirConditioner()
    {
        _factories = new Dictionary<Actions, AirConditionerFactory>();

        foreach (Actions action in Enum.GetValues(typeof(Actions)))
        {
            var factory = (AirConditionerFactory)Activator.CreateInstance(Type.GetType("FactoryMethod." + Enum.GetName(typeof(Actions), action) + "Factory"));
            _factories.Add(action, factory);
        }
    }
}

Whether we choose the first or the second example, the result should be the same:

Factory Method - factory class

There is one more thing we need to add to this class. And that is the method which is going to execute appropriate creation:

public class AirConditioner
{
    //previous constructor code

    public IAirConditioner ExecuteCreation(Actions action, double temperature) =>_factories[action].Create(temperature);
}

Now, we just have to make a call from a client. In a real-world project, we would surely check first for the current temp and then just have a factory to decide whether we should lower it or make it higher. But for sake of simplicity, we are just going to make a simple call towards our AirConditioner class:

class Program
{
    static void Main(string[] args)
    {
        var factory = new AirConditioner().ExecuteCreation(Actions.Cooling, 22.5);
        factory.Operate();
    }
}

Our result should be as expected:

Finished Factory Method

Using the Factory Method Refactoring Technique

We can use the Factory method to replace our constructor while creating an object. If our constructor consists of lots of code, we should replace it with the factory method. Furthermore, we can have multiple factory methods with meaningful names and parameter names as well which replace a single constructor.

This improves code readability a lot.

Finally, it helps us to implement a chaining syntax.

So let’s modify the AirConditioner class with the factory method:

public class AirConditioner
{
    private readonly Dictionary<Actions, AirConditionerFactory> _factories;

    private AirConditioner()
    {
        _factories = new Dictionary<Actions, AirConditionerFactory>();

        foreach (Actions action in Enum.GetValues(typeof(Actions)))
        {
            var factory = (AirConditionerFactory)Activator.CreateInstance(Type.GetType("FactoryMethod." + Enum.GetName(typeof(Actions), action) + "Factory"));
                _factories.Add(action, factory);
        }
    }

    public static AirConditioner InitializeFactories() => new AirConditioner();

    public IAirConditioner ExecuteCreation(Actions action, double temperature) =>_factories[action].Create(temperature);
}

Our client call should be modified as well:

class Program
{
    static void Main(string[] args)
    {
        AirConditioner
            .InitializeFactories()
            .ExecuteCreation(Actions.Cooling, 22.5)
            .Operate();
    }
}

Excellent. The result should be the same, but now we are using the factory method refactoring technique.

Conclusion

By reading this article, we have learned:

  • How to implement the Factory Method design pattern into the application
  • Several ways of replacing switch-case statements by using a dictionary or reflection
  • How to refactor your code by using the Factory Method Refactoring Technique

 

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!