Singleton

Ensure a class only has a single instance, and provide a global point of access to it.

Concept

A class cannot have more than one instance in an application. Once the instance is created for the singleton class, any client should use same instance whenever needed. This restricts unnecessary object creations in a centralized application. In many cases, this approach improves the application maintainability.

Analogy

A single database connection object shared by multiple objects, as creating a new database connection for every object may be costly operation.

Implementation In Java

In java there are multiple ways to create a singleton class. Implementations can be categorized as

Lazy Implementation

In lazy implementation, objects are created only when the client requires the singleton object for first time. Then it will live in memory until there are no references and garbage collector cleans up.

Few implementations mentioned in the article are:

Eager Implementation

As opposed by lazy instantiation, Eager implementation instantiates the singleton class as soon as the class is loaded into the memory.

An example implementation mentioned in the article:

Note:

In java classes are loaded only once. In the newer versions of java, classes are loaded just in time when they are used (not necessarily eager).

Class Diagram

Following is the Class diagram for singleton implementation.

classDiagram
  class Singleton {
    +Singleton singleton$
    -Singleton()
    +getInstance()$ Singleton
    +dosomething()
  }

  class Client {
    +process()
  }

  Client --> Singleton
  Singleton --> "0..1" Singleton: -singleton

Illustration

  • Singleton class must have a private constructor. By making the constructor private, the class cannot be extended by any other class and cannot be instantiated outside the class.
  • getInstance() and the instance variable must be static
  • For thread safety, use synchronized keyword

Double-Checked Lock Implementation

In double-checked lock implementation, singleton object availability is checked even before the getting to the synchronized block.

Synchronized block is needed to avoid accidental creation on multiple singleton objects.

Let’s take a scenario, where there is no synchronized block and two threads are trying to create the singleton object. While thread one creates the object, the singleton attribute is still null and the second thread can enter into the if block to create the singleton object. By the time thread one created the singleton object, second thread may be creating another instance of singleton object. In this case, two singleton objects will be created.

class Singleton {
    //    singleton static attribute
    private static Singleton singleton;

    //    private constructor
    private Singleton() {}

    public static Singleton getInstance() {
        //  double checked locking
        if (singleton == null) {
            //  synchronized block
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    //  other methods
    public void doSomething() {
      // do something
    }
}

Bill Push’s Implementation

Bill Push’s implementation is simpler implementation to create a singleton object without synchronized block in a multithreaded application.

In this implementation, private static inner class and final attribute is used to create a singleton object.

class Singleton {
    //    private constructor
    private Singleton() { }

    //  private static inner class
    private static class SingletonHelper {
        //  nested class is referenced after getInstance() is called
        public static final Singleton singleton = new Singleton();
    }

    //  get singleton instance
    public static Singleton getInstance() {
        return SingletonHelper.singleton;
    }

    //  other class methods
    public void doSomething() {
        //  doSomething
    }
}

Single Threaded Implementation

This is a simple and unsafe solution for creating the singleton object. There can be chances of multiple instantiations of single class.

class Singleton {
    //  static private attribute
    private static Singleton singleton;

    //    private constructor
    private Singleton() { }

    // simple implementation without synchronized block
    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }

    //  other class methods
    public void doSomething() {
        //  do something
    }
}

Eager Implementation

In java classes are loaded only once and static entities are executed as soon as classes are loaded into jvm. When the singleton attribute is static and final there can be only one singleton object for an application.

But this implementation can create instance even when singleton object is not needed or used by any client in the application. It also adds latencies to the application startup time as the object creation is a costly operation.

class Singleton {
    // private static singleton method
    private static final Singleton singleton = new Singleton();

    //  private constructor
    private Singleton() { }

    //  instance accessor
    public Singleton getInstance() {
        return singleton;
    }

    //  other class methods
    public void doSomething() {
        //  do something
    }
}

Usage In Client

Usage of singleton class in the client

class Client {
    public void process() {
        Singleton singleton = Singleton.getInstance();
    }
}

Advantages

  • Control over object creation
  • Create once and use multiple times.
  • Effective memory usage

Disadvantages

  • Difficult to implement in a multithreaded environment
  • Over use even when it is not required can create anti patterns and make code maintainability difficult
  • Multiple class loaders can lead to multiple instances creation in eager implementation.

When To Use

use when you want to

  • Have only one instance of class if it should be accessible globally.
  • Make a class read only
  • Prevent many stateless instances of a class with no data.

Known Uses

Usually Singletons are used for global configurations.

Java

  • The simplest example would be LogManager in java
LogManager.getLogManager();
  • Every Java application has a single instance of class Runtime to interface with the running application environment. The current runtime can be obtained from the getRuntime() method.
Runtime.getRuntime();
  • Several creational patterns can be implemented using the singleton pattern
  • Even patterns such as Facade, State many use Singleton in their implementation

Learn other design patterns

Subscribe For More Content