Singleton Pattern

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

Bates and SierraHead First Design Patterns

Class Diagram

/images/posts/design-patterns/singleton.jpg

Singleton is name of the class but also the type of the unique instance variable. The variable is static so it belongs to the class. The method getInstance() is static so can be access using Singleton.getInstance().

Key Points

  • Private Constructor. The class cannot be instantiated.

  • Core. The Singleton class
    • manages the single instance,
    • prevent other class from creating their instances,
    • provide a global access point to the instance,
    • can have its own data and methods.
  • Lazy Initialization. The instance is created only the first time the method getInstance() is invoked. When the class is loaded by the class loader the instance is not yet created. Beneficial in case of resource intensive objects such as database connection.
  • Multiple Class Loaders. Each class loader defines a namespace so the same class is loaded multiple times. A custom class loader could be define to address the issue.
  • No Subclassing. Due to the private constructor the class cannot be instantiated and subclassed. If the constructor will be changed to public, the parent and the subclasses will share the same instance variable. A static variable means it belongs to the class.

  • Garbage Collector 1.2 A curious issue happens in its implementation because the GC collected the singleton without a global reference to them. The only reference to a singleton is the singleton itself.

Implementation

public class Singleton {
    private static Singleton instance;

    private Singleton() { }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
   }
   // other data and methods
}

Multi-Threaded Application

The Singleton could be used in a multithreaded environment. Two threads could enter the getInstance() method at the same time. Ensure that each thread waits its turn before entering the method.

Different implementations are feasible in order to address the issue.

Lazy Implementation

public class Singleton {
    private static Singleton instance;

    private Singleton() { }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            istance = new Singleton();
        }
        return instance;
    }
    // other data and methods
}

Note. Synchronizing the getInstance() method creates an important overhead for the application, performance can decrease by a factor of 100.

Eager Implementation

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
         return instance;
    }
    // other data and methods
}

Note. The JVM will create an instance of Singleton when the class is loaded. Fine if the application always uses a Singleton instance.

Double-Checked Locking Implementation

public class Singleton {
	private volatile static Singleton instance;

	private Singleton() {}

	public static Singleton getInstance() {
		if (instance == null) {
			synchronized (Singleton.class) {
				if (instance == null) {
					instance = new Singleton();
				}
			}
		}
		return instance;
	}
	// other data and methods
}

Note. Just the creation of the instance is synchronized because the issue comes from a possible concurrent creation and avoid the reduction of the performance. Synchronization happens only the first time the issue has to be created. The volatile keyword

Prior Java5 an out-of-order write may allow the reference to be returned before the object was created. The new operator is not atomic.

Drawbacks

  • Global state. Singletons introduce a global state into a program
    • anyone can access to the reference variable provided by Singleton ignoring the scope;
    • global state state are very difficult to test;
    • singleton user and singleton class become coupled together so really difficult to test
      • solution: pass the singleton as parameter in the client’s constructor so the singleton can be mocked
    • factory class or the client could enforce the singularity eliminating the global state
      • issue: violation of the Single Responsibility Principle, the class should take care about its own task and the singularity
  • Dependencies. Singleton can be accessed anywhere thanks to the static method getInstance(), no need to pass the reference variable as parameter.
    • issues:
      • the signatures of the methods do not show their dependency anymore, the method could pull a singleton “out of thin air” [4];
      • becomes more difficult to use and test the code, the developer should have a look at the inner code.
  • Test-driven and Agile Development. Have small tests covering most of the code
    • test must be run in any order
    • two test could modify a shared resource that is the singleton

References

IBM - User Your Singletons Wisely [1] Portland Pattern Repository - Pages about singleton [2] Portland Pattern Repository - Singletons Are Evil [3] Google - Why Singletons Are Controversial [4] JavaWorld - Simply Singleton [5] Interview questions about singleton [6]