The Abstract Factory Pattern
The first pattern to learn
Building blocks
The abstract factory pattern is probably the most-used pattern in my toolbox. It can be distilled down to one simple concept — a class that creates instances of another class.
Of course it’s a lil bit more than that, a factory class will return a concrete implementation of an interface and the consuming class won’t care which one it receives because it will call methods as agreed upon by the interface.
But why would we want to do such a thing?
Unify the providers
Imagine you had a financial app and for whatever reason your app used more than one credit card provider. Each provider will have specific concrete ways of interacting with your app. You could of course litter your code with some if/then/else statements which would handle the different implementations as you go:
if(provider = "stripe")
{
stripeApi.Charge(amount);
}
else if(provider = "clover")
{
cloverApi.ChargeCard(amount)
}
...
//somewhere else
if(provider = "stripe")
{
stripeApi.Refund(amount);
}
else if(provider = "clover")
{
cloverApi.RefundCard(amount)
}Obviously this is difficult to manage as you’d have to have this sort of logic anywhere you needed to use a credit card provider. This approach requires that we instantiate both providers but in the end never using one of them during the request. On top of that, if you ever needed to add a third, you’d be adding even more code all over the place.
It would be much more ideal to instead have code that looked like this:
_provider.Charge(amount);
...
//somewhere else
_provider.Refund(amount);In order to have code like this, you have to do two things:
Unify all of your providers into a common interface
Instantiate the correct provider when needed
For the interface, it will take you a little bit of work to figure out what common things the providers share. Be sure to focus on using non-vendor specific methods and arguments (e.g. use primitives if possible) like so:
public interface ICreditCardProvider
{
bool Charge(decimal amount);
bool Refund(decimal amount);
}Now that we have a unified interface, let’s build our factory.
Hiding complexity
In the real world, factories take in raw materials and output finished products. What happens within the walls of the factory are private and only known to the internals of the factory. To the outside world, we see inputs go in and output come out.
Our factory will need to return a concrete implementation of either our Stripe or Clover providers. The factory will just need to take some input and it will dutifully return an instance of ICreditCardProvider:
public class CreditCardProviderFactory
{
public ICreditCardProvider GetProvider(int providerType)
{
switch(providerType)
{
case 1:
return new StripeProvider();
case 2:
return new CloverProvider();
}
}
}And each provider will need to implement ICreditCardServiceProvider:
public class StripeProvider : ICreditCardServiceProvider
{
...
}public class CloverProvider : ICreditCardServiceProvider
{
...
}Now in our consuming code, instead of instantiating the providers directly, we’ll instead ask the factory to “make” us one based on the input:
var factory = new CreditCardProviderFactory();
var provider = factory.GetProvider(1);//returns a Stripe ProviderNow of course this is a trivial example, but if we needed to get any secrets and provide them to the constructors; we’d do so in the factory and hide the complexity of putting together all of the things that are required for each provider. If you’re using a DI container, you’ll likely need to avoid new’ing them up yourself and have your container handle that.
Factories using Dependency Injection
Factories often manifest in DI as simple registration methods as well. Let’s examine a couple examples:
//for parameterless ctor's
builder.Services.AddScoped<ICreditCardProvider, StripeProvider>();
//for a ctor that requires another dependency
builder.Services.AddScoped<ICreditCardProvider>(x =>
{
var secretManager = x.GetService<ISecretManager>();
return new StripeProvider(secretManager.GetSecret("stripe_key"));
});While it may not seem like it, the first one is a factory; it just happens to use a constructor with no parameters. The second example resembles a more classic factory example. As you can we are able to pass parameters to the constructor and even use another dependency as input.
When the DI container is asked to build an ICreditCardProvider, it will know exactly what to do since we’ve provided a delegate with the recipe. In the case where you have multiple providers, you can register each provider and then inject the whole list of providers to a factory class:
public class CreditCardFactory
{
public CreditCardFactory(IEnumerable<ICreditCardProvider> providers)
{
}
...
public ICreditCardProvider GetProvider(int providerId)
{
//your logic here
}
}The downside to the above is that each time your factory is created, you are asking your DI container to provide you a list of fully instantiated providers when you only really need one. I have a better way.
Delegate Factory
When I don’t know what concrete implementation I need until run-time, I like to use a delegate factory. The reason I do it this way is to avoid putting any references to the DI container outside of program.cs/startup.cs. Let’s take a look at how this this happens:
builder.Services.AddScoped<StripeProvider>(); //concrete
builder.Services.AddScoped<CloverProvider>(); //concrete
builder.Services.AddScoped<ICreditCardFactory>(x =>
{
//instantiate with a func delegate
return new CreditCardFactory(providerId =>
{
switch (providerId)
{
case 1:
return x.GetRequiredService<StripeProvider>();
case 2:
return x.GetRequiredService<CloverProvider>();
}
throw new NotImplementedException();
});
});The first thing we’ll do is register our credit card providers in their concrete form (e.g. without need for the interface in the registration). Then we will register a CreditCardFactory that is injected into our consuming class. The magic with factory registration is the func delegate. You’ll see how this is used in a bit, but for now, take note of the func we’re passing into the ctor. This func allows us to reference the container here and avoid the ServiceProvider from needing injected into any class (which we know is bad).
Injecting the
ServiceProviderinto your class is known as the Service Locator Pattern which will attract unwanted attention in a code review as it’s commonly thought of as an anti-pattern (e.g. makes your code hard to test).
The factory class is really not doing much besides calling the func:
public interface ICreditCardFactory
{
ICreditCardProvider GetProvider(int providerId);
}
public class CreditCardFactory : ICreditCardFactory
{
private readonly Func<int, ICreditCardProvider> _func;
public CreditCardFactory(Func<int, ICreditCardProvider> func)
{
_func = func;
}
public ICreditCardProvider GetProvider(int providerId)
{
return _func.Invoke(providerId);
}
}Then to stick the landing, we inject our ICreditCardFactory into our consuming class:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ICreditCardFactory _creditCardFactory;
public WeatherForecastController(ICreditCardFactory creditCardFactory)
{
_creditCardFactory = creditCardFactory;
}
[HttpGet]
public IActionResult Get()
{
var stripeProvider = _creditCardFactory.GetProvider(1);
var cloverProvider = _creditCardFactory.GetProvider(2);
return Ok();
}
}Of course your mileage will vary, but that’s all you have to do to get an instance at run-time with some sort of input. I hope you find some use out of the factory pattern as it centralizes the construction of your dependencies.
You can find a full-working example here!
Happy coding!


Great article, as usual! This is my favorite pattern. You have a great way of explaining things, and that delegate factory is excellent!