Chapter 2. Design Patterns

2.1.  Design a class using the Singleton design pattern

[Note]

According to the GoF book, the Singleton design pattern "ensures a class has only one instance, and provides a global point of access to it." You use the Singleton pattern to satisfy four simultaneous requirements:

  • An application must have EXACTLY ONE instance of a particular class.

  • The sole instance must be accessible to clients from a well-known access point.

  • The sole instance should be extensible by subclassing.

  • Clients must be able to use and extend the instance without modifying their own code.

The Singleton design pattern ensures that the application has only one global instance of an object. The pattern's code is quite simple, but behind this simplicity, the pattern has some potential pitfalls.

The figure below shows a UML diagram for the Singleton design pattern:

Figure 2.1.  A UML diagram for the Singleton design pattern.

A UML diagram for the Singleton design pattern.


In order to write a singleton class, you'll need to understand the following:

  • Creating a static variable of the instance of your singleton class will ensure that there are no two instances created at any given point.

  • Exposing a method named getInstance() will return the instance of the class: either by creating it or returning the instance if it already exists.

  • Singletons class constructor is declared as private so that the class could not be initialized from outside.

The following code implements the concept of lazy initialization — meaning, you are creating the object of the singleton class, only when the getInstance() method is invoked. It also means that if the getInstance() method is not invoked, then the instance shall never be created:

public class Singleton {

    private static Singleton instance;

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (null == instance) {
            instance = new Singleton();
        }
        return instance;
    }
}
					

Using the synchronized keyword in this way will be extremely costly, because it's acted upon every time the getInstance() method is invoked.

There is a different technique to avoid performance bottlenecks in applications, and this is to modify the code to synchronize only the assignment in the getInstance() method:

public class Singleton {

    private static Singleton instance;

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
					

This solution is thread-safe with eager instantiation:

public class Singleton {

    private static final Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}
					

The initialization on demand holder (lazy-loaded) solution:

public class Singleton {

    // Private constructor prevents instantiation from other classes
    private Singleton() {
    }

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance()
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder {
        public static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
					

The single-element enum type solution (from "Effective Java" 2nd edition by Joshua Bloch):

public enum Singleton {
    INSTANCE;
}
					

or

public enum Singleton {
    INSTANCE;

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
					

Professional hosting         Free 'Oracle Certified Expert Web Services Developer 6' Guide     Free SCDJWS 5.0 Guide