Design pattern - The Singleton

Card Puncher Data Processing

About

The singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.

Singletons usually are used to provide a single point of access to a global service. It doesn't have to instantiate the object. It just has to provide access to the object. The object returned can be set by any means necessary.

Example

Database

Application uses database connection pooling, so one DB connection can be shared among many requests. The singleton is usually the object which manages this pool.

Instantiation

A singleton with parameters is NOT a singleton because you may have more object than one of them.

If you want your singleton to be initialized with some data, you may pass them after initialization (or via a builder pattern)

SingletonObj singleton = SingletonObj.getInstance();
singleton.init(paramA, paramB); // init the object with data

Anti-Pattern

Singletons are an anti-pattern. They have private constructor and they are then very hard to subclass and configure.

Implementation Type

Static (Language-specific)

You can implement singletons by using language-specific features, such as the static keyword for Java

Object

A singleton allows access to a single created instance that can be:

  • passed as a parameter to other methods,
  • treated as a normal object.
  • and therefore can implement interface

Object Implementation

From the less desirable to the most desirable solution.

Method Initialization

public class MethodInitializationSingleton {

    private static MethodInitializationSingleton singleton;

    private MethodInitializationSingleton() {
    }

    public static MethodInitializationSingleton getSingleton() {
        if (singleton == null) {
            singleton = new MethodInitializationSingleton();
        }

        return singleton;
    }

}

This implementation is not Thread-safe. If two threads, Thread 1 and Thread 2, call getInstance() at the same time, two instances can be created.

If Thread 1 is pre-empted just after it enters the if block and control is subsequently given to Thread 2.

Class initialization

Class initialization (ie Eager initialization) with a static initialization block in order to manage exception.

public class ClassInitializationSingleton {

    private static final ClassInitializationSingleton singleton;

    static {
        try {
            singleton = new ClassInitializationSingleton();
        } catch (Exception e) {
            throw new RuntimeException("An error occurred!", e);
        }
    }
    
    private ClassInitializationSingleton() {
    }

    public static ClassInitializationSingleton getSingleton() {
        return singleton;
    }

}
  • Class initialization is thread-safe because of the Java specification.
  • It is possible to instantiate more than one Singleton instance using Java reflections (by modifying the constructor to Accessible and calling it)

Synchronized Method Initialization

public class SynchronizedSingleton {
    
    private static SynchronizedSingleton singleton;

    private SynchronizedSingleton() {
    }

    public static synchronized SynchronizedSingleton getSingleton() {
        if (singleton == null) {
            singleton = new SynchronizedSingleton();
        }

        return singleton;
    }
    
}
  • Synchronized methods are quite costly.
  • It is possible to instantiate more than one Singleton instance using Java reflections (by modifying the constructor to Accessible and calling it)

Enumeration

In Java, Enumerations can contain method implementations and hence can be used to implement Singleton’s logic.

See Enum Singleton

Java

Documentation / Reference





Discover More
Card Puncher Data Processing
Design Pattern - (Static) Factory

The Factory pattern creates an instance of an object according to a given specification, sometimes provided as arguments, sometimes inferred. It's a dependency resolving approach. A factory class decouples...
Java Conceptuel Diagram
J2EE - JPA and Stateless Session Bean (EJB) as Data Access Object (DAO)

Stateless EJB session beans as Data Access Object (DAO) implementation with JPA. You must use the EntityManagerFactory to get an EntityManager The resulting EntityManager instance is a PersistenceContext/Cache...
Java Conceptuel Diagram
J2EE - Session Bean

A session bean encapsulates business logic that can be invoked programmatically by a client over local, remote, or web service client views. To access an application that is deployed on the server, the...
Java Conceptuel Diagram
Java - (Descriptor|Metadata)

Example of (Descriptor|Metadata) implementation in java. The source of the descriptor can be: in the code in an external file (xml, properties, ...) or generated (see ) The java/lang/Class...
Java Conceptuel Diagram
Java - Enum datatype

The enum data type implementation in java Because they are constants, the names of an enum type's fields are in uppercase letters. The enum declaration defines a class (called an enum type). The enum...
Card Puncher Data Processing
Jenkins - (Java) API (Object Model)

API Jenkins is primarily a set of Java classes that model the concepts of a build system. All classes are bound to URLs by using Stapler. The root of the object model is Hudson, and all the...
Card Puncher Data Processing
Scala - Object (Singleton)

Object in Scala are like classes, but for every object definition there is only one single instance (See ). It is not possible to create instances of objects using new, instead you can just access the...



Share this page:
Follow us:
Task Runner