Singleton Design Pattern

The Singleton design pattern is a creational design pattern that restricts the instantiation of a class to one single instance and provides a global point of access to that instance.

The main goal of the Singleton pattern is to ensure that a class has only one instance and to provide a way to access that instance from any part of the code. This is useful when we want to limit the number of instances of a class to only one, such as when dealing with shared resources or configurations.

The Singleton pattern involves a single class, which is responsible for creating its own unique instance and making sure that no other instances of the class can be created. The Singleton class usually provides a static method to get the single instance, which can be accessed by other parts of the code.

The Singleton pattern has a few variations, such as lazy initialization (the instance is created only when it is first needed) or eager initialization (the instance is created as soon as the class is loaded). Additionally, the thread-safety of the Singleton pattern implementation can be improved through different techniques, such as double-checked locking or using an enum.

Overall, the Singleton pattern is useful when we need to ensure that a class has only one instance and that this instance is easily accessible from any part of the code.

Common concepts in implementing the singleton design pattern:

  • Private constructor is created. It restricts the instantiation of the class from other classes.
  • Private static variable of the same class that is the only instance of the class.
  • Public static method that returns the instance of the class, this is the global access point for the outer world to get the instance of the singleton class.

Different Approaches to Singleton Design Pattern

Eager Initialization

In this approach the instance of the Singleton class is created during the class loading. Here the instance of the class will be created even if the client is not requesting the instance through getInstance. This approach can be used if the Singleton class is not using a lot of resources. But in most of the scenarios, singleton classes are created for resources such as File System, Database connections, etc. We should avoid the instantiation unless the client calls the getInstance method.Here the method does not provide any option for exception handling.

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case004/EagerInitializationSingleton.java

Clent class implementing Eager Initialization Singleton Class:

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case004/EagerInitializationSingletonClient.java

Console Output:
Eager Initialization Singleton doSomething
eagerInitializationSingletonObject1 hashcode: 123961122
Eager Initialization Singleton doSomething
eagerInitializationSingletonObject2 hashcode: 123961122

Static Block Initialization

Static block initialization of Singleton is a technique for creating a Singleton object in Java using a static block of code. In this approach, the Singleton object is created in a static block of code that is executed only once when the class is loaded by the Java Virtual Machine (JVM).

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case003/StaticBlockSingleton.java

Client implementing Static Block Singleton class:

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case003/StaticBlockSinletonClient.java
Console Output:
StaticBlockSingleton in doSomething method
staticBlockSingletonObject1 hashcode: 123961122
StaticBlockSingleton in doSomething method
staticBlockSingletonObject2 hashcode: 123961122

Lazy Initialization

Lazy initialization method is to create the singleton pattern which creates the instance in the global access method. It works fine in the single threaded environment. But it may not work properly in a multi-threaded environment if two or more threads are in the if condition at the same time.At that time different threads will get different instances of the Singleton class.

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case001/LazySingleton.java

In this example, the Singleton class has a private constructor to prevent direct instantiation of the class from outside. The class also has a static variable, instance, which holds the single instance of the class.

The getInstance() method is a static method that returns the single instance of the class. It first checks if the instance variable is null. If it is, a new instance of the class is created and assigned to the instance variable. If it is not null, the existing instance is returned.

Finally, the Singleton class has some methods, such as doSomething(), which can be called on the single instance of the class obtained through the getInstance() method.

Note that this implementation of the Singleton pattern is not thread-safe. To make it thread-safe, you can add the synchronized keyword to the getInstance() method, or use the double-checked locking idiom, or use an enum to implement the Singleton pattern.

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case001/LazySingletonClient.java
Console output:
Lazy Singleton doSomething
singletonInstance1 hashcode: 123961122
Lazy Singleton doSomething
singletonInstance2 hashcode: 123961122

The above console output shows singletonInstance1 and singletonInstance2 are the same object.

Thread Safe Singleton

The singleton class can be made thread safe by making the global access method synchronized.

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case002/ThreadSafeSingleton.java

The below given example illustrates a client using the class ThreadSafeSingleton.

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case002/ThreadSafeSingletonClient.java
Console output:
ThreadSafeSingleton in doSomething method
threadSafeSingletonObject1 hashcode: 123961122
ThreadSafeSingleton in doSomething method
threadSafeSingletonObject2 hashcode: 123961122

Reflection to destroy Singleton Pattern

Reflection can be used to destroy all the previous singleton implementation approaches. Here is an example class. Here two instances of the class are created.

https://github.com/vmstate/article-100/blob/main/src/main/java/vmstate/designpattern/singleton/case004/ReflectionSingletonClient.java
Console Output:
Eager Initialization Singleton doSomething
reflectionSingletonInstance1 hashcode: 123961122
Eager Initialization Singleton doSomething
reflectionSingletonInstance2 hashcode: 1227229563

Here we can see that the hashcode of the instance has been changed.

When can Singleton be used?

Suppose you have a functionality that just handles something or just processes something and does not need to know the state of the object. In that case, it’s not necessary to have many instances of the same object, spending memory to do something that a single instance can do. For some components, it only makes sense to have one instance in the system, for example:

  • Logger class
  • Caching
  • Database repository: If you have an object which accesses the database, it loads up the database in the constructor into memory and then gives out information about the content of the database once it’s loaded. So once you read the database, you do not need to reread it.
  • Object factory: If you have a factory that creates some components, then it’s not necessary to have more than one instance of it because a factory is not supposed to have any state.
  • Handle files: If you have a class that processes files, and you have many processes that happen at the same time, instead of having many instances to deal with this processing, you can have a single instance of this object; this way, it will save memory consumption.

Examples of popular frameworks using Singleton

Spring MVC

By default, Spring MVC controller classes are singleton in nature. When Spring creates a controller instance, it does so by default with the singleton scope. This means that only one instance of the controller class will be created and shared across all requests. This is a common practice in Spring MVC, as it helps to improve performance and reduce the memory footprint of the application. However, it is important to note that there are certain cases where a controller class may need to have a different scope than the default singleton. For example, if the controller needs to maintain state across requests, it may need to be configured with a different scope, such as session scope.

In such cases, we can use the @Scope annotation to specify a different scope for the controller class. For example:

@Controller
@Scope("session")
public class MyController {
   // ...
}

Spring Boot

By default, Spring Boot Controller classes are singleton scoped. This means that only one instance of the controller class is created by Spring's ApplicationContext, and that instance is shared across all requests.

This is because the Controller class is designed to handle incoming HTTP requests and process them, and it is generally not necessary to create a new instance of the controller for each request. By using a singleton instance, Spring Boot can manage the lifecycle of the controller and ensure that it is properly initialized and ready to handle requests.

However, it is possible to configure a controller to have a different scope, such as request or session scope, if needed. This can be done by annotating the controller class or methods with the appropriate scope annotation.

Struts 2

By default, Struts 2 action classes (which are analogous to controllers) are instantiated per request, which means that a new instance of the action class is created for each incoming request.

This is similar to the default behavior of Struts 2 controller classes, where a new instance is created per request to allow for more flexibility in managing the action's state and behavior. This also allows for easier unit testing and reduces the potential for thread-safety issues.

However, it is possible to configure an action to have a different scope, such as session or application scope, if needed. This can be done by specifying the desired scope in the Struts configuration file or by using the appropriate annotations.

That being said, it is generally not recommended to use singleton scope for Struts 2 actions, as it can lead to unpredictable behavior and thread-safety issues in a multi-threaded environment.

Struts 1

In Struts 1, the Action classes (which are analogous to controllers) are typically configured to be singleton scoped by default. This means that only one instance of the Action class is created by the Struts controller, and that instance is shared across all requests.

This is because the Action class is designed to handle incoming requests and process them, and it is generally not necessary to create a new instance of the Action for each request. By using a singleton instance, Struts can manage the lifecycle of the Action and ensure that it is properly initialized and ready to handle requests.

However, it is possible to configure an Action to have a different scope, such as request or session scope, if needed. This can be done by implementing the org.apache.struts.action.RequestProcessor interface and overriding the createAction() method to return an Action instance with the desired scope.

Hibernate ORM

Hibernate ORM uses a Singleton pattern to create a SessionFactory object that is used to create Session objects.

Java Servlet API

Java Servlet API uses Singleton pattern to create and manage Servlet objects.

Apache Log4j

Apache Log4j uses Singleton pattern to create and manage a logger object that is used to log messages in the application.

Apache Velocity

Apache Velocity uses Singleton pattern to manage the velocity engine that is used to render templates.

Post a comment