The Singleton Pattern in Java ensures a class has only one instance, and provides a global point of access to it.

Before getting into implementing Singleton Pattern, let’s go through few questions to make you understand the pattern better.

public class MyClass {

  private MyClass() {	}
  
}

What does above code do?

Yes, It is a class that cannot be instantiated because it has a private constructor. As the above class cannot be instantiated, can you think about another way to instantiate the class? Let’s look at below code.

public class MyClass {

  private MyClass() {	}
  
  public static MyClass getInstance() {
    return new MyClass();
  }
  
}

Well, getInstance() is a static method. It’s a CLASS method, you need to use the class name to reference a static method as below,

MyClass.getInstance() 

So now you can think of second way to instantiate an object.

High Level Class Diagram of Singleton Pattern

Singleton Pattern class diagram doesn’t involve multiple classes, as it all about how single class in restricted in instantiating.

Singleton Pattern Java

Ways to implement Singleton Pattern in Java

  1. Classic Singleton Pattern
  2. Static Initialized Singleton Pattern
  3. Thread-Safe Singleton Pattern
  4. “Double-Checked Locking” Singleton Pattern

And there can be other ways to implement also.

Type 1: Classic Singleton Pattern

// NOTE: This is not thread safe!

public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}
 
  public static Singleton getInstance() {
    if (uniqueInstance == null) {
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }
 
  // other useful methods here
  public String getDescription() {
    return "I'm a classic Singleton!";
  }
}
Test Classic Singleton Pattern
public class SingletonClient {
  public static void main(String[] args) {
    Singleton singleton = Singleton.getInstance();
    System.out.println(singleton.getDescription());
  }
}
Output
I'm a classic Singleton!

Type 2: Static Initialized Singleton Pattern

public class Singleton {
  private static Singleton uniqueInstance = new Singleton();
 
  private Singleton() {}
 
  public static Singleton getInstance() {
    return uniqueInstance;
  }
  
  // other useful methods here
  public String getDescription() {
    return "I'm a statically initialized Singleton!";
  }
}
Test Static Initialized pattern
public class SingletonClient {
  public static void main(String[] args) {
    Singleton singleton = Singleton.getInstance();
    System.out.println(singleton.getDescription());
  }
}
Output
I'm a statically initialized Singleton!

Create an instance of Singleton in a static initializer, this code is guaranteed to be thread safe.

Type 3: Thread-safe Singleton Pattern

public class Singleton {
  private static Singleton uniqueInstance;
 
  // other useful instance variables here
 
  private Singleton() {}
 
  public static synchronized Singleton getInstance() {
    if (uniqueInstance == null) {
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }
 
  // other useful methods here
  public String getDescription() {
    return "I'm a thread safe Singleton!";
  }
}
Test Thread-safe Pattern
public class SingletonClient {
  public static void main(String[] args) {
    Singleton singleton = Singleton.getInstance();
    System.out.println(singleton.getDescription());
  }
}
Output
I'm a thread safe Singleton!

In “Thread-safe” pattern, by adding synchronized keyword to the getInstance() we force every thread to wait its turn before it can enter the method. That is, no two threads can enter the method at the same time.

Type 4: “Double-Checked Locking” Singleton Pattern

//
// Danger!  This implementation of Singleton not
// guaranteed to work prior to Java 5
//

public class Singleton {
  private volatile static Singleton uniqueInstance;
 
  private Singleton() {}
 
  public static Singleton getInstance() {
    if (uniqueInstance == null) {
      synchronized (Singleton.class) {
        if (uniqueInstance == null) {
          uniqueInstance = new Singleton();
        }
      }
    }
    return uniqueInstance;
  }
  
  // other useful methods here
    public String getDescription() {
      return "I'm a double checked locking Singleton!";
    }
}
Test it
public class SingletonClient {
  public static void main(String[] args) {
    Singleton singleton = Singleton.getInstance();
    System.out.println(singleton.getDescription());
  }
}
Output
I'm a double checked locking Singleton!

If performance is an issue in your use of getInstance() method, then this method of implementing the Singleton can drastically reduce the overhead.

Points To Remember for Singleton Pattern in Java

  • We have static variable “uniqueInstance” to hold our one instance of the class Singleton
  • Our constructor is declared private, only Singleton can instantiate this class
  • The getInstance() method gives us a way to instantiate the class and also to return an instance of it
  • Singleton is normal class, it has other useful instance variable and methods
  • Singleton provides global access points to the instance. Whenever you need an instance, just query the class and it will hand you back the single instance.

Conclusion

While implementing Singleton can be tricky, after reading above post you are now well informed on the techniques for creating Singleton and should use them wherever you need to control the number of instances your are creating.

Please follow and like us: