Menu Close

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 sub-classes can override this method and create objects of different types.

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:

IAirConditioner interface
1
2
3
4
public interface IAirConditioner
{
    void Operate();
}

Now, we need concrete classes to implement this interface:

Cooling class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Cooling : IAirConditioner
{
    private readonly double _temperature;
 
    public Cooling(double temperature)
    {
        _temperature = temperature;
    }
 
    public void Operate()
    {
        Console.WriteLine($"Cooling the room to the required temperature of {_temperature} degrees");
    }
}
Warming class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Warming : IAirConditioner
{
    private readonly double _temperature;
 
    public Warming(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:

AirConditionerFactory abstract class
1
2
3
4
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:

CoolingFactory class
1
2
3
4
public class CoolingFactory : AirConditionerFactory
{
    public override IAirConditioner Create(double temperature) => new Cooling(temperature);
}
WarmingFactory class
1
2
3
4
public class WarmingFactory : AirConditionerFactory
{
    public override IAirConditioner Create(double temperature) => new Warming(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:

Actions enum
1
2
3
4
5
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:

AirConditioner class
1
2
3
4
5
6
7
8
9
10
11
12
13
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:

Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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:

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

AirConditioner class
1
2
3
4
5
6
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:

Program.cs
1
2
3
4
5
6
7
8
class Program
{
    static void Main(string[] args)
    {
        var factory = new AirConditioner().ExecuteCreation(Actions.Cooling, 22.5);
        factory.Operate();
    }
}

Our result should be as expected:

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:

AirConditioner class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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:

Program class
1
2
3
4
5
6
7
8
9
10
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