As one of the original patterns outlined in the book “Design Patterns: Elements of Reusable Object-Oriented Software” by the “Gang of Four”, the factory pattern is the go to pattern for constructing new objects. Aside from the singleton pattern, it is probably the most popular. Removing the direct interaction with constructors and the ‘new’ keyword, the factory pattern allows for the dependence on interfaces as opposed to specific implementations. Also, construction concerns (including injecting dependencies) is encapsulated when using the factory pattern.
As the usage of IOC Containers has gained popularity over the years, I’ve seen the factory pattern used less and less. But even in the world of IOC containers like Microsoft.DependencyInjection, Unity, Autofac, etc. the factory pattern still has many benefits.
Let’s take a practical look at implementing the factory pattern in ASP.NET Core using the new built-in container.
The first step in using an IOC container is registering all interfaces and service types. There are several extension methods that are provided out of the box.
- AddTransient – Each time a transient object is requested, a new instance will be created.
- AddScoped – The same object will be used when requested within the same request.
- AddSingleton – The same object will always be used across all requests.
With each of these, our dependency is provided directly. With a factory though, we want to be able to retrieve our dependency on demand. As such, none of these extension methods will suit our needs. For registering a factory, a custom extension method can be created.
Now when configuring the container, we can call the AddFactory function to configure our factory.
Now with our container setup, we can inject Func<T>.
This gives a few key benefits. Instantiation of our dependency is delayed allowing us to control when the object is initialized. If IDisposable is implemented, we can use the dependency within a using statement. The best part is we can do all of these things without interacting with the container directly.
Using a Factory Type
If we wanted to take this a step further, instead of using a Func as our factory, we could create an explicit factory type IFactory<T>.
To accommodate for the new factory interface, we just need to make some slight modifications to our extension method.
Now when we inject our dependency, it is more clear what the intent is.
What About Other Containers?
So now that you are convinced injecting a factory can be useful, what if you are not using the Microsoft.DependencyInjection container? Well, you might be in luck. Many containers, such as the ones listed below, support injecting factories as Func<TService> without any customizations at all.
Even in a world of dependency injection, the factory pattern still has its place. By injecting a factory, you get total control of the creation of your dependencies. With a few customization, ASP.NET Core will easily accommodate!