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.
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.
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.
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:
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:
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
What is the benefit of using an abstract class instead of an Interface for AirConditionerFactory ?
You can always try to use one instead of the other and see how it works. To be honest, I can’t remember if I had any specific benefit from using a class instead of an interface. Again, just use it as you need it in your project. If an interface fits your needs, do it that way.
Real-time scenarios are not like that of course. I want to create a factory method and inject some different dependencies into each service. Service Provider is known as anti-pattern. What do you think about using a Service provider in the factory method?
What can be the drawbacks?
Hello Helena. To be honest I don’t have any direct opinion on that. There are also different opinions on whether the Service Provider is anti-pattern or not. Software architecture is not a silver bullet, and no one can’t tell you that you have only one way of achieving your goal. So, if this works for you, keep it going and of course, always monitor performance
What if we use Dependency Injection instead of creating the Instance, will it still be a Factory Pattern. For example using the ServiceCollection
Would this still be a factory Pattern as we are not creating the instance explicitly
Software architecture is not something that can’t be changed or modified, as long as it fits your project you can modify the process. So, I am pretty sure you can use DI as well. But to be honest, I never used something as you suggested in your comment, but you are still using factories and I have nothing against it 🙂
Hi,
Everything is cool but i dont understand if i need add some new functionalities in the CoolingManager class for example IncreaseCooling(), create() method returns IAirConditioner so IncreaseCooling() method becomes unusable how to solve this problem? Or if the CoolingManager implements several intefaces, what type shoud Create() method returns?
P.S. English my third language but i’m trying my best
There is no problem with adding any new functionality in the CoolingManager class. You can add as much methods as you like. The Create() method just returns created factory based on an action you want to execute (Cooling or Warming). Once the factory is created you can call any method inside it, as we did with the Operate method.
Hi,
I think your implementation of the factory method is correct but I would suggest to use Nouns as class names.
Warming and Cooling are adjectives.
Helo Mont. Yeah, I accept that. It should have been something like CoolingConditioner or something like that. Thank you for the suggestion.
Dude! 10/10 example. I can’t even quantify how many horrific implementation examples I came across online before finding this site. Can’t thank you enough!
Hello John. Thank you very much for that. It is always nice to hear something like that from the reader. Have a nice day.
Thanks for the helpful example of Factory pattern. One thing that I had to edit is the “FactoryMethod.”
Instead I used –> typeof(AirConditioner).Namespace + “.”
Hello Eric. Thank you for your comment. I am glad you find it helpful. Thank you for the suggestion as well. Best regards.
Cool stuff
Glad to hear that.
Just amazing nice-practice explanation. Many Thanks!
You are very welcome. Thank you for your comment.
Hi,
I tried to recreate your solution in dotnet core 2.2. The problem arose when uses reflection to add action and factory.It threw a Null exception. I then downloaded your source code and it ran. Your solution worked fine.
Hello again. Well, I have just tested this solution with the .NET Core 2.2 Console Application and everything worked as it supposed to. If you still have a problem, please share your code with us and we will check it. As much as I can see, this should work without any problem.
Hello Graeme. Yes, we have used the .Net Console Application and not .NET Core Console Application. Thank you for your information, we will check that issue with dotnet core 2.2.
Hy Graeme, i had the same problem. I believe that is because of the namespace , in the project is FactoryMethod while for me it was FactoryPattern.AirConditioner.Factory.
Try this and let me know if it worked.
Btw Marinko great example !!
Thank you Andrei, for reading this article and sharing your solution with all of us. I appreciate it a lot. Best regards.
Thanks for the article!, very helpful. I had the same problem as above, you can add another reflection to get the namespace guys if you want, just insert:
GetType().Namespace+"."
instead of the string where the namespace should be (took me a while to figure out that you have to manually append the “.” Dot operator. this way the code will work in any namespace it is pasted into!
Great tip, thank yo!