Singleton pattern (Singleton): guarantees that a class has only one instance, and provides a global access point to access it.
Usually we can have a global variable that makes an object accessible, but it doesn't prevent you from instantiating multiple objects. One of the best ways is to make the class itself responsible for keeping its only instance. The class guarantees that no other instance can be accessed. is created, and it can provide a method to access the instance.
sample code
1. Lazy Mode
The Singleton class defines a getInstance operation that allows clients to access its unique instance. getInstance is a static method that is mainly responsible for creating its own unique instance
class Singleton{ private static Singleton instance; private Singleton(){ //The constructor makes it private, which blocks the possibility of using new to create such instances from the outside world } public static Singleton getInstance(){ //This method is the only global access point to get the instance of this example if (instance == null) { //If the instance does not exist, create a new instance, otherwise return the existing type instance = new Singleton(); } return instance; } }
client code
Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); if (s1 == s2) { //The result of comparing the objects after two instantiations is that the instances are the same System.out.println("The two objects are the same instance"); }
Singleton pattern because the Singleton class encapsulates its unique instance, so it can strictly control how and when clients access it, in short, controlled access to the unique instance.
2. Thread-safe lazy mode
class SingletonDemo { private static SingletonDemo instance; private SingletonDemo(){ } public static synchronized SingletonDemo getInstance(){ if(instance==null){ instance=new SingletonDemo(); } return instance; } }
However, concurrency is actually a special case. Most of the time the extra resources occupied by this lock are wasted, and the structure of this patching method is very inefficient.
3. Hungry man mode
class SingletonDemo { private static SingletonDemo instance=new SingletonDemo(); private SingletonDemo(){ } public static SingletonDemo getInstance(){ return instance; } }
Perform a loading directly when running this class, and then access it directly. Obviously, this method does not have the effect of lazy loading. Considering the comparison with static classes mentioned above, this method only has one more memory resident than static classes.
4. Static class internal loading
class SingletonDemo { private static class SingletonHolder{ private static SingletonDemo instance=new SingletonDemo(); } private SingletonDemo(){ System.out.println("Singleton has loaded"); } public static SingletonDemo getInstance(){ return SingletonHolder.instance; } }
The advantage of using inner classes is that static inner classes are not loaded when the singleton is loaded, but are loaded when the getInstance() method is called, which achieves a similar effect to the lazy mode, and this method is thread-safe .
5. Enumeration method
enum SingletonDemo{ INSTANCE; public void otherMethods(){ System.out.println("Something"); } }
client code
public class Hello { public static void main(String[] args){ SingletonDemo.INSTANCE.otherMethods(); } }
6. Double check lock method
class SingletonDemo { private volatile static SingletonDemo instance; private SingletonDemo(){ System.out.println("Singleton has loaded"); } public static SingletonDemo getInstance(){ if(instance==null){ synchronized (SingletonDemo.class){ if(instance==null){ instance=new SingletonDemo(); } } } return instance; } }
Three main points of a singleton:
- thread safety
- lazy loading
- Serialization and deserialization security