An Introduction to Factory Method Design Pattern
Overview
Factory method design pattern comes under the creational pattern and this allows the user to create objects without exposing the creational logic.
Usually, here we use parameters to create instances because this returns the objects based on the parameters we pass. The returned object might be a subclass, class with an implemented interface, extended class of an abstract class, etc.
The following describes how we can implement the factory method design pattern using a real-world example in java.
Assume, a certain company has a particular salary schema as;
The salary of the month is calculated based on the experience level (1, 2, and 3), and over time they work.
An additional amount is added to the base salary based on the experience level (1, 2, and 3) and when the total working hours exceed more than 180 h, another additional amount is also added to the base.
Here assume, the user needs to save the salary record of each employee in a database when it is getting created.
Figure 1 illustrates the general overview of the application.
To implement this scenario,
First, I have added the maven dependency mongo-java-driver to the project on pom.xml. Refer to the following code.
Next, I have implemented the database connection with DBManager class using the Singleton pattern. Here I have implemented this as a standalone application and chosen MongoDB as the database (name of the database: design_patterns, Collection name: factory_method_collection). Refer to the following code.
I have created an abstract Employee class to declare common methods and variables for all 3 subclasses. Refer to the following code.
Apart from that, I have implemented an Enum to hold the levels of the employees. Refer to the following code.
Next, I have extended the 3 subclasses inherited from the Employee class and implemented the incomplete method calculateSalary() to make them concrete. Refer to the following code.
As per this, when you are creating an instance of a subclass, immediately an employee record is stored in the database. To achieve this, I have called the salaryCalculate() and save() methods inside the constructor. Here, I have overridden the salaryCalculate() method and this is calculated based on the above-defined guidelines.
After that, I have created the EmployeeFactory class to create instances based on the employee level. Refer to the following code.
Finally, I have created employee instances using the EmployeeFactory class and used the print() method to print the details of each record. Refer to the following code.
The following defines the received outputs.
Employee ID: 1
Employee Level: LEVEL1
Hours Worked: 200
Salary: 7500.00Employee ID: 2
Employee Level: LEVEL2
Hours Worked: 40
Salary: 5500.00Employee ID: 3
Employee Level: LEVEL3
Hours Worked: 250
Salary: 6750.00Employee ID: 4
Employee Level: LEVEL2
Hours Worked: 100
Salary: 5500.00Employee ID: 5
Employee Level: LEVEL1
Hours Worked: 250
Salary: 7500.00
Conclusions
- This allows the user to create objects without exposing the creational logic.
- The objects are returned based on the parameters we pass.
References