Singleton Design Pattern is one of the simplest creational design patterns. This design pattern ensures that class has only single instance initialized and by providing means to access the class instance.
In the many scenarios we need to restrict clients to allow creation of multiple instances of the class. This design pattern can be used when,
- Creation of the object for each request is costlier.
- Class has the shared state of the global variables used across the application.
- You don't want to have code that solve one problem that scatters across multiple classes.
Few common scenarios where we can see this design pattern are followed:
- Create single connection to the database across application.
- Maintain single truth of source for user state.
- Global configuration of the application
How to implement Singleton Desing Pattern?
- Restrict the creation of class instance outside the class by making constructor private.
- Add static private global variable in the class of the same class type.
- Create public static method which check state of class instance variable and return after initializing if required.
In this blog let us take example of Database Connection class and implement using Singleton Design pattern with various approach and understand Prons and cons of each approach.
Simple Approach
In this approach we follow above mentioned simple steps to implement singleton design pattern using lazy initialization of the class instance.
package com.techtalesonline.designpattern.singletone;
public class DBConnection {
// Create static class variable of the same class
private static DBConnection dbCon;
/**
* Private constructor restrict creation of the object outside
* of the class.
*/
private DBConnection(){
}
/**
* This static method creates instance of the class if it null and return.
*/
public static DBConnection getInstance(){
if(dbCon == null){
dbCon = new DBConnection();
}
return dbCon;
}
}
Prons:
- Easy implementation
- Lazy object creation
Cons:
- It is not thread safe in multi-threaded environment.
Eager initialization Approach
In this approach we are creating instance of the class using static class variable. JVM will ensure that single instance of the class is created when class is loaded in the memory. This approach solves the problem of thread safety and ensure always there is single instance of the class.
package com.techtalesonline.designpattern.singletone;
public class DBConnection {
// Create private static class variable of the same class
private static DBConnection dbCon = new DBConnection();
/**
* Private constructor restrict creation of the object outside
* of the class.
*/
private DBConnection(){
}
/**
* This static method creates instance of the class if it null and return.
*/
public static DBConnection getInstance(){
return dbCon;
}
}
Prons:- Easy implementation
- Eager initialization of the class instance
- Thread safe as instance of the class is created while class loading.
Cons:- Waste of the resource if instance is not used in the application.
- Slow application startup if there are many classes with singleton design pattern implementation.
- Unable to pass parameters during initialization of the instance.
- Exception handling is not possible.
- Easy implementation
- Eager initialization of the class instance
- Thread safe as instance of the class is created while class loading.
- Waste of the resource if instance is not used in the application.
- Slow application startup if there are many classes with singleton design pattern implementation.
- Unable to pass parameters during initialization of the instance.
- Exception handling is not possible.
Lazy Initialization with Thread safe Approach
In this approach we go with lazy initialization of the class instance using class method. This method is marked with synchronized to resolve thread safety issue. This will ensure that only one thread get lock for class and execute method.
package com.techtalesonline.designpattern.singletone;
public class DBConnection {
// Create private static class variable of the same class
private static DBConnection dbCon;
/**
* Private constructor restrict creation of the object outside
* of the class.
*/
private DBConnection(){
}
/**
* This static method creates instance of the class if it null and return.
*/
synchronized public static DBConnection getInstance(){
if(dbCon == null){
dbCon = new DBConnection();
}
return dbCon;
}
}
Prons:- Resolve the thread safety issue.
- Lazy initialization of the instance reduces memory wastage.
Cons:- Add the overhead of wait time when multiple thread tries to access method.
- Resolve the thread safety issue.
- Lazy initialization of the instance reduces memory wastage.
- Add the overhead of wait time when multiple thread tries to access method.
Lazy initialization with Double check locking
In this approach we are making only critical section of the code as synchronized plus adding double check before creating new object, so object creation reduces wait time when multiple thread tries to access create instance method. This is achieved through synchronized code block.
package com.techtalesonline.designpattern.singletone;
public class DBConnection {
// Create private static class variable of the same class
private static DBConnection dbCon;
/**
* Private constructor restrict creation of the object outside
* of the class.
*/
private DBConnection(){
}
/**
* This static method creates instance of the class if it null and return.
*/
public static DBConnection getInstance(){
if(dbCon == null){
synchronized(DBConnection.class){
if(dbCon == null){
dbCon = new DBConnection();
}
}
}
return dbCon;
}
}
Drawback of the Singleton Pattern
- This design pattern violet Single Responsibilities Principle as it tries to solve two problems.
- Difficult to perform unit testing.
- This design pattern needs special attention in the multi-threaded environment.
Comments
Post a Comment