Singleton – Bill Pugh Solution or Enum

1. Overview

A singleton class ensures that only one instance of that class is created. To ensure point of access, the class controls instantiation of its object. Singleton classes are found in many places in JDK (Java Development Kit), such as java.lang.Runtime.

The Singleton class offers two things: one and only one instance of the class, and global single point of access to that object

2. Implementation

To implement Singleton pattern, we have different approaches but all of them have following common concepts.

  • Private constructor to prevent 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 outer world to get the instance of the singleton class.
Can we ensure that our Singleton is indeed a Singleton? We will discuss later in the article.

3. Different Approaches

  • Eager Initialization – instance of a class is created much before it is actually required
  • Lazy Initialization – instance of a class is created when the client sends a request
  • Static Block Initialization – is similar to eager initialization, except that instance of class is created in the static block that provides the option for exception handling
  • Thread Safe Singleton – create a thread-safe singleton class is to make the global access method synchronized so that only one thread can execute this method at a time
  • Bill Pugh Singleton – implementation using the static inner helper class. Static inner class is not loaded into memory until its getInstance() method is called
  • Enum Singleton – provide implicit support for thread safety and only one instance is guaranteed

Eager Initialization and Lazy Initialization works fine in a single threaded environment. It won’t be suitable in multi threaded environment.

Static Block Initialization has one drawback. If we have a class with 3 static fields and application needs to access only 1, for which, instance creation is not required at all, we still have one instance created through whether we require it or not.

Thread Safe Singleton works fine in the multi threaded environment but reduces the performance because of the cost associated with the synchronized method.

To overcome the issue of synchronization, Bill Pugh came up with his implementation using the static inner helper class. The static inner class is not loaded into memory until its getInstance() method is called.

Enum Singleton provides implicit support for thread safety and only one instance is guaranteed as per Java docs.

Then, Why the Title says Bill Pugh of Enum?

Out of all other approaches, These two approaches work well in single and multi threaded environment without performance impact.

4. Bill Pugh Singleton

Bill Pugh Singleton is based on the “initialization on demand holder” idiom. This idiom uses inner classes and does not use any synchronization construct. It uses static block but in a different way and suggests to use static inner class.

We will rewrite the above Logger program using Bill Pugh approach here

Bill Pugh Singleton is the best approach so far, however, it can be easily destroyed with the use of Java reflection.

When you run the above class, you will notice that hashCode of both the instances are not same which destroys the singleton pattern.

5. Enum Singleton

To overcome this situation with Reflection, Joshua Bloch suggests the use of Enum to implement Singleton design pattern as Java ensures that any enum value is instantiated only once in a Java program.  However, the obvious drawback is we cannot have lazy loading in Enum.

Logger class will look like this using Enum Singleton

to get the instance client need to call Logger.INSTANCE.

What if we need serialization for Singleton?

If the Singleton class implements java.io.Serializable and a singleton object is serialized and then deserialized more than once, there will be multiple instances of Singleton.

In order to avoid serialization issue, implement readResolve() method in Logger Singleton class as below:

6. Conclusion

We have discussed different approaches to create Singleton class and mainly focused on Bill Pugh and Enum approaches. Out of these two, I feel Enum pattern is better as this approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiations, even in the face of sophisticated serialization or reflection attacks.

harinathk
 

Click Here to Leave a Comment Below 0 comments