This tutorial explain the basic concept of singleton design pattern and how to use them. This is one of the pattern I have published as part of our Design pattern in Java series. If you are interested in receiving updates, please subscribe our newsletter.
Situations often will demand for the existence of only one object for a particular class in an Application. For example, the existence of only one Database Connection for a particular session, one object referencing the set of Global properties being shared across the various modules, etc.
Such classes are candidates to be designated as Singleton classes. The sole purpose of such a class is to ensure that only one instance of the class is created for the entire application and that instance is shared across multiple clients.
Additional Reading:
How to Write Singleton Design Pattern?
So, how to make a class to behave as a Singleton class? For example, let us consider the class, say MyConnection
, which we wish to make as a Singleton class. Given below is the class definition,
MyConnection.java
package tips.pattern.singleton; public class MyConnection { private static MyConnection connection = new MyConnection(); private MyConnection() { } public static MyConnection getConnection() { return connection; } }
Note that we have declared a static object called connection
which is of type MyConnection
. Also note that declaration of the private constructor which tells that no other outside classes can directly instantiate this class. The only way to get a reference to the MyConnection
object is to make a call to the static
method MyConnection.getConnection()
.
What happens if the client calls MyConnection.getConnection()
multiple times? Since the connection object is maintained as a static object, multiple calls to MyConnection.getConnection()
will return a reference pointing to the same object. This can be proven by the following code,
MyConnectionConsumer.java
package tips.pattern.singleton; public class MyConnectionConsumer { public static void main(String[] args) { MyConnection connection1 = MyConnection.getConnection(); MyConnection connection2 = MyConnection.getConnection(); if (connection1 == connection2) { System.out .println("Both the references are pointing to the same object"); } else { System.out.println("Objects are not equal"); } } }
The output of the above program will be “Both the references are pointing to the same object”. There is one major flaw in our singleton class declaration. What if the client doesn’t use the MyConnection
class? Since the connection object is maintained as a static object, the object will be loaded during the time of MyConnection
class loading itself. So, let us prevent this by making the following changes,
MyConnection.java
package tips.pattern.singleton; public class MyConnection { private static MyConnection connection = null; private MyConnection() { } public static MyConnection getConnection() { initObject(); return connection; } private static void initObject() { if (connection == null) { connection = new MyConnection(); } } }
Two well-known changes are noted in the code. One is the static object connection
is not initialized in the declaration itself. The second change is the introduction of the new method initObject()
which gets called whenever a clients request for the Objecr by calling MyConnection.getConnection()
. The method initObject()
creates a new object for the very first time only by making a comparison check.
Will the class works well in a multi-threaded environment? Certainly not. Why? Imagine two threads trying to access the MyConnection.getConnection()
method. So, it is always wise to synchronize the object creation logic in the implementation. So the final revised code looks similar to this.
private static void initObject(){ synchronized (MyConnection.class) { if (connection == null){ connection = new MyConnection(); } } }
When to use Singleton Design Pattern
There is no definite answer for this question. The common thinking is that where there is a requirement to have only one instance of the class for the entire application, then singleton is the suitable answer.