Design Patterns: Constructing things in the Factory pattern
This is the seventh instalment of my series on design patterns in software. For the introduction to the whole series, definitely check out Design Patterns: Introduction with Singletons. This initial post describes general information about design patterns as well. The complexity of the factory pattern is comparable to the singleton pattern.
The Factory pattern is another creational pattern, like the Singleton, that is supposed to help you manage the creation of objects. In object oriented languages, you construct objects quite frequently in code. Occasionally, several implementations of a certain interface or extensions of abstract classes all represent types of entities. Creating these entities can get quite messy, and it might be useful to do all of that in a centralized location.
We are going to look at the simple factory pattern (with a method that creates objects) and the factory method pattern (a superclass with subclasses). We're going to skip the Abstract Factory pattern for now.
As per usual, a simple UML diagram showing the outline of this pattern (the simple factory on the left and the factory method on the right):
Let's first eliminate a confusing factor here. As you can see, the simple factory has a method for creating the objects. This means that the client has a direct reference to the factory and not to an abstraction of it. The fact that it has a method for object creation, does not mean it is the Factory Method pattern. This confuses a lot of people.
The second factor is that the Factory Method pattern uses an abstraction layer as association endpoint, and concrete subclasses for object creation. This means that the client has a reference to the abstract class, yet instantiates it with the concrete class. Again, even though this uses abstraction, this is not the Abstract Factory pattern... More confusion!
The name of the pattern implies the way (inside the pattern) how objects are created and are not referring to the way the client is communicating with the implementation of the pattern.
So, in short: the simple factory uses a method that creates the objects. The factory method uses an abstract layer and concrete classes for object creation.
It is a creational pattern, which means that this pattern should help you organize the creation of objects and make your creational code less complex. This pattern helps centralizing object creation into a single class / structure of classes instead of having it spread throughout your application. You'll organize your code and make sure you don't depend on implementations of classes too much.
Here it is again, the open/closed principle. By using a factory pattern to create objects of classes within a family, you can clear the client code and have it simply talk to interfaces (interface segregation). The client then no longer cares about the implementations. It is then quite easy to extend the family of classes with new classes and place them in the factory. Voila, the factory and thus application has been extended.
When you apply reflection to this pattern, you can completely remove code changes in the factory pattern and have a reflection algorithm search for implementations in a certain namespace. This, however, is a different story.
Reusability can happen with plenty of patterns, however with the Factory patterns this might be a big one. When you implement this pattern correctly, you have very loose coupling and high cohesion. This means that theoretically, the factories you make, can be reused in other projects at any time. In game development, a lot of game development companies have engines built upon a lot of design patterns. A lot of character / entity creation is based on factory patterns, often with some form of reflection or configuration, to be able to reuse these factories in future games.
Instead of having to unit test all parts of a piece of software where objects of a certain family are created, you'll only have to test if the factory pattern works as it should. You test to see if the expected objects are returned from any of the factory patterns. This simplifies a lot of unit tests.
Example in TypeScript
The example is very simple. It is merely a simple factory method implementation that will create renderable objects based on a provided type. In the example code, renderable objects are created in two locations. One inside the Application class and one at the point where the Application instance is accessed. This example is far from fancy, but is meant to demonstrate the purpose of the pattern. As shown in the UML diagram below, the package is on its own and can be used in future projects.
Check out this pen.
I hope that I managed to explain this pattern well, as it is one of my favourite ones, like the Composite pattern. I love feedback, so let me know if I need to change anything or adjust the format. I want this to be as educational and understandable as it can be! I'll write about the Chain of Responsibility pattern next, which should simplify request handling in code.