avatarNicklas Millard

Summary

This article discusses an approach to implementing the factory design pattern without using logical statements such as switch and if-else, making it more extensible and maintainable.

Abstract

The factory design pattern is a fundamental concept in software development, but many tutorials showcase implementations that are hard to extend due to the use of logical statements like switch and if-else. The author proposes an alternative approach that uses a private dictionary to store possible types a factory class can create, allowing for easy extensibility. This approach eliminates the need to modify the factory class when new types are added, adhering to the Open/Closed principle. The article demonstrates this concept with a car factory example, showing how to register new car types and create objects using the factory class. The author also provides performance comparisons between the proposed factory approach and traditional switch-based implementations.

Bullet points

  • The factory design pattern is a fundamental concept in software development.
  • Traditional factory implementations using logical statements like switch and if-else can be hard to extend.
  • The proposed approach uses a private dictionary to store possible types a factory class can create.
  • This approach allows for easy extensibility and adheres to the Open/Closed principle.
  • The article demonstrates the concept with a car factory example.
  • The author provides performance comparisons between the proposed factory approach and traditional switch-based implementations.

APPLIED DESIGN PATTERNS: Factory

Factory Pattern Without Switch, This Is How It Should Be Done

My approach to creating easily extensible factory classes without logical statements such as switch and if-else

You’ve come to the right place if you’re struggling with the factory pattern or wondering how to create a factory class without switching and if-else statements.

From the sheer number of StackOverflow posts regarding this, I can tell you are not alone.

I’ll drop my 2 cents on how you can implement the factory pattern without any use of code branching. I think you’ll find my approach helpful as it provides you something I couldn’t easily get an answer for back when I was a beginner.

Let’s get some context first

The factory pattern is one of those very fundamental patterns I’m almost sure every developer ever has heard of. I won’t preach theory, so in the unlikely event you haven’t heard of the factory pattern, go do some quick research and get back here.

The vast amount of tutorials showcases some mind-numbing, hard-to-extend, factory based on branching logic.

The issue with logical statements such as switch and if-else in a factory class is whenever you’re developing some new type it should be able to create, you’ll have to modify the factory itself.

This clearly violates the Open/Closes principle.

🔔 Want more articles like this? Sign up here.

When is an approach considered better?

We might have different interpretations of what’s great.

Some developers — often more junior ones — prefer if-else above all else. It’s insanely easy to implement and it’s performant. For a very simple and small codebase, a factory implemented with logical statements might be tolerable.

To me, great code is easy to read, extend, and maintain. We achieve all this following the approach I’m about to show you.

“Show me the solution already!”

I’ll show an example that might be slightly contrived due to its extreme simplicity, but it serves to demonstrate the different parts of a factory class and its use.

I can’t anticipate all your needs. I’ll make this generic enough for anyone to get the point, and you’ll then need to apply your requirements to it.

Okay… I’ll quit beating around the bush and finally get into it.

So, for this demonstration, we’re going to create a car factory, as I suppose everyone can imagine what that’d be like.

Basic classes the factory is going to create

We have an abstractCar base class and a few classes implementing the Car class. Nothing fancy.

What you’ve come for is this code snippet below. Take whatever time you need to read it. I’ll walk you thru how it works afterward.

Extensible factory class without logical statements such as if-else and switch

To make our factory extensible, we’ll use a private dictionary to hold all possible types we can create. Adding new car types is as easy as calling the RegisterCar method, providing a key called ‘carType’ and a function returning a Car type.

We see the ‘factoryMethod’ is stored at the end of ‘RegisterCar’. This allows us to configure the factory from somewhere else, e.g. at application startup.

Then, we have two ways of creating a car. Either by using the Indexer on the factory object, or, by using the CreateCar method. Both are equally valid options.

Let’s put it to the test.

We’re creating a small test to validate the factory class creates an object of the correct type.

A simple test that verifies our factory class works

I’m using the xUnit test framework for .NET. This framework has a pretty handy feature called Theory which allows us to define a single test and provide it with multiple data sets thru the [InlineData] attribute.

Tests pass and everyone’s happy.

Let’s wire it up with a web application

Fine, we got a CarFactory now. It’s all nice and dandy but how do we use this in a real web application?

First, we’ll need to register our factory class with the dependency injection framework. I’ll be using the standard Microsoft DI framework provided to us out of the box.

Here, IServiceCollection is basically the DI container. I’m sure your DI framework of choice has something similar.

Registering the factory class with the dependency injection framework

Whenever another class takes a CarFactory as a constructor argument, it receives an instance configured with three registered car types as shown above.

Using our factory in a web controller is as easy as letting the controller have a dependency on CarFactory and then just use its methods. It’s all wired up already.

Simple controller using the Factory Class

At this point, making a request to api/cars returns ["Mercedes-A180", "Audi-A5", "Audi-A5-Convertible"].

A request to api/cars/Audi-A5 returns a JSON serialized version of our Audi A5 registration:{ "model": "A5" }.

Adding new classes to the factory is easy

You’ll just need to register an object with an associated key when you register the factory with the dependency framework, and that’s it.

There’s no a whole lot more to this point.

What’s performance like?

I did a simple performance test to get a better understanding of how performant a factory class in relation to using a switch.

In the test itself, I’m just instantiating a Car based on a string provided to either the switch or factory class. The time in milliseconds is the accumulated time of doing 1 million iterations.

Tests are run on a MacBook Pro 2015 model 2.5 GHz with 16GB 1600 MHz DDR3 RAM.

Performance table of doing 1 million iterations

The switch test is as you expect. We’re basically just having a switch statement that picks the car type to instantiate. That’s likely the typical factory class implementation you’re used to seeing.

Factory1 test is conducted in a way that for each iteration, the factory class is instantiated and 3 car types are registered with it. Then, as in the switch, a Car type is instantiated based on string input.

Factory2 test is much like the previous test. However, the major difference is the factory class is only instantiated once with its 3 car types registered. Then, a Car type is instantiated based on string input.

We can also use reflection

My approach will still require you to manually go register a new Car type with our factory object. If you want to avoid this, you’ll need to do some reflection work.

Reflection is a great tool when you want your code to be extremely flexible and extensible. However, it’s outside the scope of this article. I’d just like to let you know that’s also a viable option.

Resources for the curious
-------------------------
Factory Pattern by oodesign.com

Nicklas Millard is a software development engineer in one of the fastest-growing banks, building mission-critical financial services infrastructure.

Previously, he was a Big4 Senior Tech Consultant developing software for commercial clients and government institutions.

New YouTube Channel (@Nicklas Millard)

Connect on LinkedIn

Technology
Software Development
Software Engineering
Programming
Web Development
Recommended from ReadMedium