Factory design pattern is the most commonly used design pattern in today's programming world. Let's have the study of this pattern on our agenda here. In this blog we will understand what is the Factory design pattern? When can it be used? What are the advantages and the drawbacks of using this pattern? But, the crucial thing that we learn here today is how to implement the factory design pattern in Java.
We will use examples to clarify the concepts of this pattern. At the end of this session, we will achieve 2 goals:
- Be able to analyze our requirement or code and decide whether we can apply factory pattern to it
- And, actual application and implementation of the factory design pattern in java
What is a Factory design Pattern?
A Factory design pattern also known as the "Factory Method pattern" is a type of Creational design patterns. By the name we can guess it produces or creates something, in our case objects. This design pattern deals with object creation without providing a specific class type for the object.
Now one might think, how can there be a situation where the program does not know which objects to create? To answer this question, consider a scenario where we want to send a notification to the user. There are 2 ways in which the user can receive the notifications. One is either by an email, or as an SMS.
Now the user decides at run time in which format he wants to receive the notification. As a result, our program doesn't know until runtime which notification object to create.
This is where Factory method pattern comes to our rescue. Let's take a closer look at how this pattern solves our problem.
In the figure above you can see two different users with different needs for notification. One prefers email notification while other prefers SMS/mobile notification. Thus typically our implementation for both the notifications is not the same. And because of this our application doesn't know which notification to send until the user tells it at the run time.
To solve this problem we instantiate a factory in the factory pattern. This factory is then responsible to give us the object of the type specified at run time.
Where to use Factory Pattern
- We need to create different type of objects
- Object creation is dynamic – at run time we need to decide which object to be created
- Different methods contain same object creation code
How does the Factory Pattern work?
Firstly, what the Factory pattern does is, it replaces the object creation (using 'new') by a factory method. This factory method in turn creates objects for us using 'new'. So, the question arises isn't the removal of 'new' from one part of the code just to add it to some other part of the code pointless?
Consider this, now we have a separate method to create objects. Hence, this method can be used by different classes to create objects at run time.
Our code that will further use these objects is called as the client code. This client is unaware of the exact type and creation process of the object. Thus, It treats all the objects as the they are of base type. Which means in our example above, our client will not know whether the object it receives is a object of type Email or SMS. It will treat all the objects as if they are objects of type Notification.
Now, we shall take our example and try to implement it. Also, you can try implementing as you read this blog. And, tell us in the comment section below whether you were successfully able to implement the pattern or not.
Implementing Factory Design Pattern in Java
Let us further, understand the UML diagram given above.
- As discussed above we have two type of notifactions to send Email and SMS. So we have created 'NotificationExecutor' interface, And two classes namely, 'EmailNoificationExecutor' and 'SMSNotificationExecutor' to implement this interface. Each one of these implementations have their own version of the method 'executeNotification()' within them.
- Then we have created 'NotificationExecutorFactory' for providing the instance of a 'NotificationExecutor'
- We will use getNotificationExecutor() of factory class to get the desired instance by type
- Client class called 'NotificationSender' will use factory to get instance and triggers notification sending action.
Thus, depending upon the parameter passed to the method 'getNotificationExecutor(String executorType)' of 'NotificationExecutorFactory', the overridden method 'executeNotification()' of either of the two implementations of 'NotificationExecutor' is called.
How to do in Java
After we have understood the flow of the pattern with the above UML, we shall now proceed with the programmatical implementation of the Factory pattern in Java. As per the diagram above,
1) Firstly, let us create an interface for notification executors,
package main.java.creational.factorymetthod;
public interface NotificationExecutor {
public void executeNotification();
}
2) Secondly, we will create 2 implementing classes for this interface. These classes will then override the 'executeNotification()' method according to their sending mechanism. These implementations will look like this
package main.java.creational.factorymetthod;
public class EmailNotificationExecutor implements NotificationExecutor {
@Override
public void executeNotification() {
System.out.println("Email notification sent");
}
}
This being 'EmailNotificationExecutor', and the other one being 'SMSNotificationExecutor'
package main.java.creational.factorymetthod
public class SMSNotificationExecutor implements NotificationExecutor {
@Override
public void executeNotification() {
System.out.println("SMS notification sent.");
}
}
3) Then, what we need is a factory to generate the instances of the specific executors according to the 'executorType'
package main.java.creational.factorymetthod;
public class NotificationExecutorFactory {
public static NotificationExecutor getNotificationExecutor(String executorType) {
if(executorType.equals("Email"))
return new EmailNotificationExecutor();
if(executorType.equals("SMS"))
return new SMSNotificationExecutor();
return null;
}
}
4) And finally, we create a class that triggers our notification action
package main.java.creational.factorymetthod;
public class NotificationSender {
public static void main(String[] args) {
NotificationExecutorFactory.getNotificationExecutor("Email").executeNotification();
}
}
Here we can see, first we get the executor instance of the type 'Email' as per the argument to getNotificationExecutor() method. Lastly, the respective implementation of method executeNotification() is invoked for that instance.
Benefits
- Creation of different types of objects is possible at run time
- It separates the object creation logic from the object usage logic
- Removes duplicate code
- Thus, makes changing or addition to object creation easier
Limitations
- The different types of objects created must have the same parent class
- The addition of new classes and interfaces could increase the complexity of the code
Fast track reading
- Type of Creational design pattern
- Also, called as Factory Method pattern
- Most commonly used design pattern
- Further, enables to create objects by deciding the type of object at run time
- Then, helps to isolate the object creation logic to a single method
- This method can be further overridden by different classes
- Hence avoids repetition of code
Well explained with good examples 👍
Thank you for the feedback.
It is our goal to help programmers like all of us understand different concepts of programming. And also help them apply it to their day to day work.
Your appreciation means a lot to us and is a great motivation.
Stay tuned for more such interesting content. Happy coding!!