Singleton mode
for some classes, only one object instance is allowed, and a method to obtain its object instance [static method] is provided
Singleton pattern structure
a singleton class declares a static method named getInstance to get an instance to return the same instance of its class.
and its construction method needs to be hidden, that is, getInstance() is the only method that can get the instance
Embodiment in Java:
1. Add a private static member variable to the class to hold the singleton instance.
2. Declare a public static build method to get a singleton instance.
3. Implement "deferred initialization" in static methods. This method creates a new object the first time it is called and stores it in a static member variable. After that, the method returns the instance every time it is called.
4. Make the constructor of the class private. Class can still call constructors, but other objects cannot.
5. Check the client code and replace the call to the constructor of the singleton with a call to its static build method
classification
Hungry Han formula (static constant)
hungry Chinese style is to directly new the instance in memory
class Singleton{ //2. Create object instances within this class private final static Singleton instance = new Singleton(); //1. Privatization of constructor private Singleton(){ } //3. Provide public static methods to return instance objects public static Singleton getInstance(){ return instance; } } public class SingletonTest { public static void main(String[] args) { Singleton instance1 = Singleton.getInstance(); Singleton instance2 = instance1; System.out.println(instance1 == instance2);//true System.out.print(instance1.hashCode()+"|"); System.out.println(instance2.hashCode()); //1325547227|1325547227 } }
advantage:
instantiation is completed during class loading to avoid thread synchronization
Disadvantages:
the effect of Lazy Loading is not achieved
if this instance is not used, it will cause a waste of memory
Hungry Chinese (static code block)
class Singleton{ private static Singleton instance; private Singleton(){ } //In a static code block, create a singleton object static { instance = new Singleton(); } public static Singleton getInstance(){ return instance; } }
Lazy (thread unsafe)
lazy means that the object is new in memory only when the instance is got.
class Singleton{ private static Singleton instance; private Singleton(){ } //Provide a static public method //When using this method, take the step of creating instance public static Singleton getInstance(){ if (instance == null){ instance = new Singleton(); } return instance; } }
Advantages and disadvantages:
it has the effect of Lazy Loading. But it can only be used under single thread
in multithreading, if a process enters the if judgment and has not yet been executed, and other threads also pass the judgment statement, multiple instances will be generated
In actual development, this method is not used
Lazy (thread safety, synchronization method)
class Singleton{ private static Singleton instance; private Singleton(){ } //Add synchronous processing code to solve the problem of thread insecurity public static synchronized Singleton getInstance(){ if (instance == null){ instance = new Singleton(); } return instance; } }
Advantages and disadvantages:
solves the problem of thread insecurity
but the efficiency is too low. When each thread wants to obtain the instance, it needs to synchronize when entering the getInstance method, and the method only needs to be executed once. If it needs to obtain the instance later, they can return directly.
Lazy (thread unsafe, synchronous code block)
class Singleton{ private static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if (instance == null){ //Add synchronous processing code to solve the problem of thread insecurity synchronized (Singleton.class) { instance = new Singleton(); } } return instance; } }
the original intention is to improve the previous one
but it does not play the role of thread synchronization. Because it is easy to generate multiple instances when entering the if judgment.
duplication check
class Singleton{ private static volatile Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if (instance == null){ synchronized (Singleton.class) { if (instance == null){ instance = new Singleton(); } } } return instance; } }
Description of advantages and disadvantages:
double checking is often used in multithreading development. Two if judgments ensure thread safety.
instantiate the code only once. Improve efficiency.
Static inner class
features of static inner class:
when loading a class, it will not be loaded. Ensure lazy loading.
when calling, the class will be loaded [and only once]. Ensure thread safety
class Singleton{ private Singleton(){ } //Static inner class with a static attribute private static class SingletonInstance{ private static final Singleton INSTANCE = new Singleton(); } //Returns the static properties of the static inner class public static Singleton getInstance(){ return SingletonInstance.INSTANCE; } }
Advantages and disadvantages:
class loading mechanism is adopted to ensure that there is only one thread for initialization
static internal classes will not be instantiated immediately when external classes are loaded. SingletonInstance class will be loaded only when getInstance() is called to complete instantiation
enumeration
enum Singleton{ INSTANCE; public void sayOK(){ System.out.println("This is OK."); } } public class SingletonTest { public static void main(String[] args) { Singleton instance1 = Singleton.INSTANCE; Singleton instance2 = Singleton.INSTANCE; System.out.println(instance1 == instance2);//true System.out.print(instance1.hashCode()+"|"); System.out.println(instance2.hashCode()); //1325547227|1325547227 instance1.sayOK();//This is OK. } }
Advantages and disadvantages:
with the help of enumeration implementation, it can not only avoid the problem of multi-threaded synchronization, but also prevent the reproduction of deserialization and the creation of new objects.
👍 It is also the way advocated by Josh Bloch, the author of Effective Java
Application scenario of singleton mode
if a class in the program has only one instance available for all clients, the singleton mode can be used.
if you need to control global variables more strictly, you can use singleton mode.
Advantages and disadvantages
advantages:
✔️ You can guarantee that a class has only one instance
✔️ You have obtained a global access node to the instance
✔️ A singleton object is initialized only when it is first requested
disadvantages:
❌ Singleton mode may mask bad design, such as too much mutual understanding between program components.
❌ This mode needs to be processed in a multi-threaded environment, so it is necessary to avoid multiple threads creating singleton objects multiple times.
❌ Singleton client code unit testing can be difficult because many test frameworks create mock objects in an inheritance based manner. Since the constructor of a singleton class is private, and most languages cannot override static methods, you need to think of ways to simulate singletons carefully. Either don't write test code at all, or don't use singleton mode.