HFDP(5) - Singleton Pattern
Published: 2023-01-16 10:23:57

In this post we will introduce the Singleton Pattern. 

In many ways, Singleton is very like the global variables. But Singleton could be lazily loaded. Singleton Pattern ensures there is at most one instance of a class and that is globally accessible. For example, we may want the database connection and logging to be a singleton. 

Singleton is a class with _private_ constructors. The only way to get an instance of it is via a static method `getInstance`. 

## Formal Definition 
> The **Singleton Pattern** ensures a class has only one instance, and provides a global point of access to it.

## Implementation

### For Single Thread (non thread-safe)
```java
public class Singleton {
    private static Singleton uniqueInstance;

    // other useful instance variables here

    private Singleton() {
        // initialize
    }

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }

    // other useful methods here
}
```
However, if java runs multithread, unqueInstance might be created more than once. This is not what we want. 

### Synchronized
It is straightforward to solve the thread safety issue by adding `synchronized` keyword to getInstance method. (TODO: ...detailed explanation here... )

```java
public class Singleton {
    private static Singleton uniqueInstance;

    // other useful instance variables here

    private Singleton() {
        // initialize
    }

    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }

    // other useful methods here
}
```

However, synchronization is expensive. 

### Eager Initialization 
```java
public class Singleton {
    private static Singleton uniqueInstance = new Singleton();

    // other useful instance variables here

    private Singleton() {
        // initialize
    }

    public static Singleton getInstance() {
        return uniqueInstance;
    }

    // other useful methods here
}
```
If the Singleton is bound to be used, we could use eager initialization, making sure the instance is available from the start. This certainly solves the expensive synchronization issue. 

However, one problem with this approach is if the Singleton is resource intensive (initialization is expensive), and we may not use it in the whole program. It is advised to turn to other methods. 

### Double-checked locking 
```java
public class Singleton {
    private volatile static Singleton uniqueInstance;

    // other useful instance variables here

    private Singleton() {
        // initialize
    }

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            // Check for an instance and if there isn’t one,
            // enter a synchronized block.
            synchronized (Singleton.class) {
                // Note we only synchronize the
                // first time through
                if (uniqueInstance == null) {
                    // Once in the block, check again and if
                    // still null, create an instance.
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }

    // other useful methods here
}
``` 
If performance is an issue, use this method. However, it might be an overkill for some simpler problems. 

## Diagram 


![Singleton](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s2qwyypxxrdb00ahsed.png)


Singleton Pattern is probably the most simple design pattern. That's it for today. See you next post!