Monday, July 25, 2022

5 Ways to implement Singleton Design Pattern in Java? Examples

Hello guys, While Singleton is anti pattern nowadays and dependency injection is better choice as it helps unit testing, its good to know about Singleton pattern, especially if you are in the business of maintaining large and old code base. This article introduces the singleton design pattern and its 5 implementation variations in Java. You will learn different ways to implement a singleton pattern and understand the challenges of creating a singleton class, like thread-safety issues and serialization issues.

Problem
At most, one instance of a class must be created in an application.

Solution
That class (singleton) is defined, including its own instance, and the constructor must be private.



What is Singleton Design Pattern in Java?

Singleton Design Pattern is a popular pattern to keep a global variable. It's a class with a getInstance() method, which is both public and static so that any class which needs a reference to this class can call this method and get the global reference.

If you are interested in learning more about design patterns, you can also see these Design Pattern in Java courses on Udemy to learn more about design patterns and their modern implementations. It's one of the best courses and contains modern implementations of classic Java design patterns using modern features.

Here is the UML diagram of Singleton design pattern in Java and then we'll see how you can implement Singleton pattern in Java:

5 Ways to implement Singleton Design Pattern in Java


1. Lazy initialization, non-thread-safe:

This is the classical version, but it's not thread-safe. If more than one thread attempts to access instance at the same time, more than one instance may be created.
public class Singleton {
    private static Singleton instance = null;
    public static Singleton Instance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    private Singleton() {}
}


2. Non-lazy initialization, thread-safe

This is the simplest thread-safe version, but it does not support lazy initialization.
public class Singleton {
    private static volatile  Singleton instance = new Singleton();
    public static Singleton Instance() {
        return instance;
    }
    private Singleton() {}
}


3. Lazy initialization, thread-safe

This version supports both properties but has performance problems. Once a thread uses a singleton instance, the others have to wait because of the lock.
public class Singleton {
    private static Singleton instance = null;
    private static readonly object lockObj = new object();
    public static Singleton Instance() {
        lock (lockObj) {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    privat



4. Double-check locking

This is an improved version of the third solution. Two null checks prevent lock waits for the most time, but not always. Also, it does not work properly for Java because of the Java memory management approach.  If you want, you can also learn more about double checked locking in singleton here. It's also one of the common Java interview question and asked in banks like HSBC, Citi etc. 

public class Singleton {
    private static Singleton instance = null;
    private static object lockObj = new object();
    public static Singleton Instance() {
        if (instance == null) {
            lock (lockObj) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    private Singleton() {}
}



5. Nested initialization

A nested class is used for lazy initialization. This version is also thread-safe, but a bit complex. For most situations, solutions 2 or 4 will be suitable according to performance parameters.

public class Singleton {
    public static Singleton Instance() {
         return Nested.instance;
    }
    private Singleton() {}

    class Nested {
        static Nested() {}
        internal static readonly Singleton instance = new Singleton();
    }
}

Usage:

public static void main (string[] args) {
    Singleton instance = Singleton.Instance();
}

That's all about how to implement the Singleton Design Pattern in Java. I have shown you 5 different implementations of the Singleton pattern in Java. You can use any of the above methods to create Singleton for your project, though I recommend Enum Singleton pattern because of its simplicity and full proof nature.


If you like this article and interested in learning more about design patterns and principles, you may like following ones as well :
  • 5 Free Courses to learn Object Oriented Programming (courses)
  • What is the difference between Adapter, Decorator, and Proxy design patterns? (answer)
  • Why implementing Singleton using Enum is better than Class in Java? (answer)
  • What is the difference between Association, Aggregation, and Composition in OOP? (answer)
  • What is the Open-Closed design Principle in OOP? (answer)
  • What is the difference between Factory and Abstract Factory Design Patterns? (answer)
  • 5 Reasons to use Composition in place of Inheritance in Java? (answer)
  • How to implement the Strategy Design Pattern using Java Enum? (solution)
  • What is the difference between State and Strategy patterns in Java? (answer)
  • How to implement the Builder design pattern in Java? (solution)
  • 10 Object-Oriented Design Principle Every Programmer Should know (principles)
  • Top 5 Books to Learn Design Patterns and Principles (books)
  • How to implement DAO design Pattern in Java? (answer)
  • What is the difference between Singleton and Static Class in Java? (answer)
  • Why should you Interface for Coding in Java? (answer)
  • A real-life example of the Decorator Pattern in Java? (example)
  • 5 Online Courses to learn Design Pattern in Java (courses)

Thanks for reading this article so far. If you like this article about the Singleton Pattern in Java, then please share it with your friends and colleagues. If you have any questions or feedback, then please drop a note.

3 comments:

  1. this page has got many not accurate code

    ReplyDelete
    Replies
    1. Hello Anonymous, would you mind to clarify which code is not accurate and why? that will help us correct and also the readers.

      Delete
  2. The declaration of constructor with the static keyword is not a correct declaration in Java language.
    There is also no "internal" and "readonly" keyword in the language.

    ReplyDelete

Feel free to comment, ask questions if you have any doubt.