Singleton Design Pattern
Design Patterns
Programming
Software Development
Object-Oriented Programming

How do you implement the Singleton design pattern?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

The Singleton design pattern is a software design pattern that restricts the instantiation of a class to one single instance. This is useful when exactly one object is needed to coordinate actions across the system. Common uses include controlling concurrency or serving as a central point of access for resources like database connections.

Understanding Singleton Pattern

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. It involves two components:

  • A private constructor to restrict instantiation of the class from outside the class.
  • A static method that allows clients to access the instance.

Implementation Steps

1. Create the Singleton Class

A typical implementation in Java might look like this:

java
1public class Singleton {
2    private static Singleton instance;
3
4    private Singleton() { }
5
6    public static Singleton getInstance() {
7        if (instance == null) {
8            instance = new Singleton();
9        }
10        return instance;
11    }
12}

In this example, the Singleton class has:

  • A private static variable of the same class that is the only instance of the class.
  • A private constructor to forbid using the new operator outside the class.
  • A public static method that returns the instance of the class, this is the global access point for the outer world to get the instance of the singleton class.

2. Thread Safe Singleton

The basic implementation shown above does not handle multi-threaded situations well. If multiple threads try to get the instance of the Singleton class at the same time, it might create multiple instances. To solve this issue, synchronization can be used:

java
1public class Singleton {
2    private static Singleton instance;
3
4    private Singleton() { }
5
6    public static synchronized Singleton getInstance() {
7        if (instance == null) {
8            instance = new Singleton();
9        }
10        return instance;
11    }
12}

3. Double-checked Locking

To avoid the overhead of synchronization each time the instance is required, double-checked locking can be employed:

java
1public class Singleton {
2    private static volatile Singleton instance;
3
4    private Singleton() { }
5
6    public static Singleton getInstance() {
7        if (instance == null) {
8            synchronized (Singleton.class) {
9                if (instance == null) {
10                    instance = new Singleton();
11                }
12            }
13        }
14        return instance;
15    }
16}

4. Bill Pugh Singleton Implementation

An alternative and more concise method for creating singletons in Java is using an inner static helper class:

java
1public class Singleton {
2    private Singleton() { }
3
4    private static class SingletonHelper {
5        private static final Singleton INSTANCE = new Singleton();
6    }
7
8    public static Singleton getInstance() {
9        return SingletonHelper.INSTANCE;
10    }
11}

In this case, the inner class is not loaded until the method getInstance() is called, providing a solution to the multi-threading problem without synchronization.

Table Summary

ApproachThread SafeLazy InitializationProsCons
Basic ImplementationNoYesSimple to implementNot thread safe
Synchronized MethodYesYesThread safeHigh overhead
Double-checked LockingYesYesLess overhead than sync methodComplex implementation
Bill Pugh MethodYesYesReduces complexity, thread safeRequires understanding of classes

Conclusion

The Singleton design pattern is essential for scenarios where only one instance of a class should exist. Various implementations have their own trade-offs between simplicity, performance, and thread safety. Choosing the right implementation of the Singleton pattern depends on the specific problem you're trying to solve and the specific constraints of the system in which you're working.


Course illustration
Course illustration

All Rights Reserved.