Hi friends. Alex Versus with you.
What’s the point?
The Factory method, also known as the Virtual Constructor, is an astounding design pattern that defines a common interface for creating objects in a parent class and allows you to modify the created objects in child classes.
The pattern allows a class to delegate object creation to subclasses. Used when:
- The class does not know in advance what subclasses it needs to create.
- Responsibilities are delegated to the subclass, and knowledge of which subclass takes on those responsibilities is localized.
- Created objects of the parent class are specialized in subclasses.
What problem does it solve?
Imagine you have created a food delivery management program. The program uses an electric scooter as the only delivery vehicle. Your e-scooter couriers deliver food from point A to point B. It’s simple.
The program is gaining popularity and your business is growing. The scooter fleet is limited and you decide to connect bicycles, taxis, quadcopters and courier robots to your delivery system. It is important for you to know when the food will be delivered and how many units of food the courier can pick up. The new vehicles have different speeds and capacities.
You find that most of your entities in the program are strongly related to the Scooter object, and in order to make your program work with other delivery methods, you will have to add links to 80% of your codebase and repeat this for each new transport. Familiar situation?
As a result, you will end up with terrifying code filled with conditional statements that perform one or another action, depending on the transport.
And what’s the solution?
The factory method offers to create transport objects by calling a special method. Subclasses of the class that contains the factory method can modify the generated objects of the specific created transports. At first glance, this may seem pointless: we just moved the call to the constructor from one end of the program to the other. But now you can override the factory method in your subclass to change the type of transport you create.
For such a system to work, all returned objects have a common interface, and subclasses can produce objects of different classes that have a common interface.
For the client of the factory method, there is no difference between the created objects, since he treats them as some kind of abstract Transport. It is important for him that this object can deliver food from point A to point B, but how exactly he will do this is not important.
Let’s look at the class diagram of this approach.
An example of implementation in PHP can be studied here. Since Golang lacks OOP features such as classes and inheritance, it is impossible to implement this pattern in the classical form. Regardless, we can implement the basic version of the pattern — Simple Factory.
In our example, there is a file called iTransport.go, which defines the methods for creating food delivery vehicles. We will store the transport entity in a structure (struct) that uses the iTransport interface. We also implement the Factory.go file, which represents the factory for creating the necessary objects. The client code is implemented in the main.go file. Instead of directly creating concrete transport objects, the client code will use the getTransport (t string) factory method to do this, passing the desired object type as an argument to the function.
When to use?
- When we want to give the opportunity to expand our library. Using this approach, the user of your library can create new concrete implementations of the classes of their objects, and the creation of these objects will be assigned to the factory method of your library.
- The factory method separates the object creation code from the rest of the code. The code for creating these objects can be extended without changing the main program code. To create a new object of your product, you just need to create a new subclass and define a factory method in it that returns the product you need in the required configuration.
What are the benefits?
- Removes the object creation layer from specific product classes.
- Selects the production code of products in one place, making it easier to maintain the code. Simplifies the addition of new products to the program.
- It implements the open — closed principle (OCP) — the OOP principle, which establishes the following position: “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”
What are the disadvantages?
May lead to the creation of large parallel class hierarchies, since for each product class its own creator subclass must be created.
Use the Factory Method template when you want to seamlessly inject new objects with new configurations into your program to interact with the main business logic.