Abstract Factory in Typescript (GoF Design Pattern)
Abstract factory: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
If we follow Alexander Shvets checklist for using abstract factory we need to check each item of this checklist…
Check list
- Decide if “platform independence” and creation services are the current source of pain.
- Map out a matrix of “platforms” versus “products”.
- Define a factory interface that consists of a factory method per product.
- Define a factory derived class for each platform that encapsulates all references to the
new
operator. - The client should retire all references to
new
, and use the factory methods to create the product objects.
Here we have…
- - Yes, create objects is my source of pain because I have 4 objects but it could be more something like ‘50’ objects.
- My matrix of platforms vs products objects in general look like this.
We can have a matrix or a table of nxn where each cell value will be the product of a specific platform to return through a method.
But for my specific purpose my matrix will be …
As you can see is only a 2x2 matrix with 4 different objects to return through a method.
3. We are going to define a factory interface in this case we will use an abstract class because interfaces can be abstract classes too and this class will have 2 factory methods defined by products columns in this case :
- getLeftDoor()
-getRightDoor()
So my Abstract Factory will be like this
4. We define a concrete factory class for each platform (row of the table) and we will encapsulate all references to the new
operator.
5. Last step is to use the factory methods but before we need a static method in the abstract factory ( CarPart class ) for returning a factory…
in this static method we return a factory wich can be a hondaFactory or a mazdaFactory, we make use of an enum for avoiding errors.
So now everything is ready to use this static factory method for proving a concrete factory and get products(objects) from it.
Output:
Now we can easily exchange factories, and get products from it.
Conclusion:
Abstract factory provide a static method for providing factories and then use each factory to return a set of objects this is good because we follow this principles:
Program to an interface, not an implementation
In this case interface is an abstract class specifically an abstract factory.
Depend upon abstractions. Do not depend upon concrete classes.
We depend of an abstract factory not a concrete factory , we can have not only two factories but N different factories each one considered a family of a set of related objects.
Favor composition over inheritance
We favoured composition in static method where we have an instance each one for each factory also this will return an only instance we will avoid returning a new instance in each call.
Encapsulate that varies
The only thing that varies is what kind of left door or right door is returned and we will encapsulated this by providing methods
getLeftDoor();
getRightDoor();
we avoid having something like:
getHondaLeftDoor();
getHondaRightDoor();
getMazdaLeftDoor();
getMazdaRightDoor();
Because what if we would like to have another 3 car models? therefore we will need another 6 methods!!! that would be insane…
we avoid doing another 6 methods by just doing 2 abstract methods and providing a factory that will take care of instantiate and return correctly the products.
And we make exchangeable factories just by changing a simple parameter in CarPart.getFactory(parameter);
Abstract factory is a creational pattern that allow us to create and return N different products( Objects ) each one belonging to a N different families( Factories );
That’s why my conclusion is that:
Abstract factory can solve the problem of getting products of an NxN table where rows are platforms and columns are products…
Final Code: