Singleton Pattern
# Singleton Pattern
## Singleton Pattern
The Singleton Pattern is one of the simplest design patterns in Java. This type of pattern is a creational pattern and provides one of the best ways to create an object.
This pattern involves a single class which is responsible to create an object while making sure that only single object gets created. This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class.
The Singleton pattern is a creational design pattern that ensures a class has only one instance and provides a global point of access to that instance.
**Note:**
* 1. A singleton class can have only one instance.
* 2. A singleton class must create its own unique instance.
* 3. A singleton class must provide this instance to all other objects.
### Singleton Pattern
### Intent
Ensure a class has only one instance and provide a global point of access to it.
### Problem
Solve the problem of creating and destroying instances of globally used classes frequently.
### When to Use
When you need to control the number of instances and save system resources.
### Solution
Check if an instance of the singleton already exists in the system. If it does, return that instance; if not, create a new one.
### Key Code
The constructor is private.
### Application Examples
* A class has only one head teacher.
* When Windows operates files in a multi-process, multi-threaded environment, it avoids multiple processes or threads operating on the same file simultaneously, requiring processing through a unique instance.
* The device manager is designed as a singleton pattern. For example, a computer has two printers to avoid printing the same file at the same time.
### Advantages
* There is only one instance in memory, reducing memory overhead, especially when instances are created and destroyed frequently (such as caching the homepage of a management college).
* Avoids multiple occupations of resources (such as file writing operations).
### Disadvantages
* No interface, cannot be inherited.
* Conflicts with the Single Responsibility Principle. A class should only care about internal logic, not about the way it is instantiated.
### Use Cases
* Generating unique serial numbers.
* Counters in WEB applications, avoiding incrementing the count in the database every time the page is refreshed by caching it first.
* Creating objects that consume too many resources, such as I/O and database connections.
### Notes
* **Thread Safety**: The `getInstance()` method needs to use a synchronization lock `synchronized (Singleton.class)` to prevent multiple threads from entering simultaneously and creating multiple instances.
* **Lazy Initialization**: The instance is created when the `getInstance()` method is called for the first time.
* **Serialization and Deserialization**: Override the `readResolve` method to ensure that deserialization does not create a new instance.
* **Reflection Attack**: Add protection code in the constructor to prevent creating new instances via reflection.
* **ClassLoader Issues**: Be aware that complex classloader environments may lead to multiple instance problems.
### Structure
The Singleton pattern includes the following main roles:
* Singleton Class: The class that contains the singleton instance, typically declaring the constructor as private.
* Static Member Variable: A static member variable used to store the singleton instance.
* Get Instance Method: A static method used to obtain the singleton instance.
* Private Constructor: Prevents external direct instantiation of the singleton class.
* Thread Safety Handling: Ensures that the creation of the singleton instance is safe in a multi-threaded environment.
We will create a _SingleObject_ class. The _SingleObject_ class has its private constructor and a static instance of itself.
The _SingleObject_ class provides a static method for the outside world to get its static instance. The _SingletonPatternDemo_ class uses the _SingleObject_ class to get the _SingleObject_ object.

### Step 1
Create a Singleton class.
## SingleObject.java
public class SingleObject{private static SingleObject instance = new SingleObject(); private SingleObject(){}public static SingleObject getInstance(){return instance; }public void showMessage(){System.out.println("Hello World!"); }}
### Step 2
Get the unique object from the singleton class.
## SingletonPatternDemo.java
public class SingletonPatternDemo{public static void main(String[]args){SingleObject object = SingleObject.getInstance(); object.showMessage(); }}
### Step 3
Execute the program and output the result:
Hello World!
There are multiple ways to implement the Singleton pattern, as shown below:
### 1. Lazy Initialization, Not Thread-Safe
**Is Lazy Initialization:** Yes
**Is Thread-Safe:** No
**Implementation Difficulty:** Easy
**Description:** This is the most basic implementation. The biggest problem with this implementation is that it does not support multi-threading. Because no lock `synchronized` is added, strictly speaking, it is not a singleton pattern.
This method has obvious lazy loading and does not require thread safety. It does not work properly in a multi-threaded environment.
## Example
public class Singleton{private static Singleton instance; private Singleton(){}public static Singleton getInstance(){if(instance == null){instance = new Singleton(); }return instance; }}
**The following implementation methods all support multi-threading, but there are differences in performance.**
### 2. Lazy Initialization, Thread-Safe
**Is Lazy Initialization:** Yes
**Is Thread-Safe:** Yes
**Implementation Difficulty:** Easy
**Description:** This method has good lazy loading and works well in a multi-threaded environment, but it is very inefficient. In 99% of cases, synchronization is not needed.
Advantages: Initialization only occurs on the first call, avoiding memory waste.
Disadvantages: Must add a lock `synchronized` to ensure singleton, but adding a lock affects performance.
The performance of `getInstance()` is not critical to the application (this method is not used frequently).
## Example
public class Singleton{private static Singleton instance; private Singleton(){}public static synchronized Singleton getInstance(){if(instance == null){instance = new Singleton(); }return instance; }}
### 3. Eager Initialization
**Is Lazy Initialization:** No
**Is Thread-Safe:** Yes
**Implementation Difficulty:** Easy
**Description:** This method is commonly used but can easily create garbage objects.
Advantages: No lock is added, so execution efficiency is improved.
Disadvantages: Initialization occurs when the class is loaded, wasting memory.
It avoids multi-threaded synchronization problems based on the classloader mechanism. However, the instance is instantiated when the class is loaded. Although there are many reasons for class loading, in the singleton pattern, most are due to calling the `getInstance` method. However, it cannot be ruled out that other methods (or other static methods) may cause class loading. At this time, initializing the instance obviously does not achieve the lazy loading effect.
## Example
public class Singleton{private static Singleton instance = new Singleton(); private Singleton(){}public static Singleton getInstance(){return instance; }}
### 4. Double-Checked Locking (DCL)
**JDK Version:** Starting from JDK1.5
**Is Lazy Initialization:** Yes
**Is Thread-Safe:** Yes
**Implementation Difficulty:** Relatively complex
**Description:** This method uses a double-lock mechanism, which is safe and maintains high performance in a multi-threaded environment.
The performance of `getInstance()` is critical to the application.
## Example
public class Singleton{private volatile static Singleton singleton; private Singleton(){}public static Singleton getSingleton(){if(singleton == null){synchronized(Singleton.class){if(singleton == null){singleton = new Singleton(); }}}return singleton; }}
### 5. Initialization-on-Demand Holder Idiom (Static Inner Class)
**Is Lazy Initialization:** Yes
**Is Thread-Safe:** Yes
**Implementation Difficulty:** Moderate
**Description:** This method achieves the same effect as the double-checked locking method but is simpler to implement. For lazy initialization of static fields, this method should be used instead of double-checked locking. This method is only applicable to static fields. Double-checked locking can be used when instance fields need lazy initialization.
This method also uses the classloader mechanism to ensure that only one thread initializes the instance. Unlike the third method, where the instance is instantiated as soon as the Singleton class is loaded (not achieving lazy loading), in this method, the instance is not necessarily initialized when the Singleton class is loaded. Because the SingletonHolder class is not actively used, it will only be explicitly loaded when the `getInstance` method is explicitly called, thereby instantiating the instance. Imagine if instantiating the instance consumes a lot of resources, so you want it to be lazy-loaded. On the other hand, you do not want it to be instantiated when the Singleton class is loaded, because you cannot ensure that the Singleton class might be actively used elsewhere and thus loaded. In this case, instantifying the instance is obviously inappropriate. At this time, this method is more reasonable than the third method.
## Example
public class Singleton{private static class SingletonHolder{private static final Singleton INSTANCE = new Singleton(); }private Singleton(){}public static final Singleton getInstance(){return SingletonHolder.INSTANCE; }}
### 6. Enum
**JDK Version:** Starting from JDK1.5
**Is Lazy Initialization:** No
**Is Thread-Safe:** Yes
**Implementation Difficulty:** Easy
**Description:** This implementation has not been widely adopted, but it is the best way to implement the singleton pattern. It is more concise, automatically supports serialization, and absolutely prevents multiple instantiations.
This method is advocated by Josh Bloch, the author of Effective Java. It not only avoids multi-threaded synchronization problems but also automatically supports serialization, preventing deserialization from creating new objects and absolutely preventing multiple instantiations. However, since the enum feature was added after JDK1.5, writing it this way may feel unfamiliar. In practice, it is rarely used.
Private constructors cannot be called via reflection attacks.
## Example
public enum Singleton{INSTANCE; public void whateverMethod(){}}
**Experience:** Generally, the first and second lazy initialization methods are not recommended. The third eager initialization method is recommended. Only when you explicitly need to implement lazy loading should the fifth initialization-on-demand holder idiom be used. If deserialization is involved in creating objects, you can try the sixth enum method. If there are other special requirements, consider using the fourth double-checked locking method.
YouTip