Design pattern - singleton pattern
1.1. brief introduction
For example, in Java development, we all know that one or more classes and object instances can be created through new, and the singleton mode is to take certain measures to ensure that there can only be one object instance of a class in the whole system, and the method to obtain the class instance can only be a static method to obtain its instance provided by the class itself.
1.2. Use sample
For example, the singleton pattern is used in the doGetBean method in the Spring source code, as follows:
Summary of single case mode cognition:
1. A class has only one instance; 2. Instances of classes can only be created by themselves; 3. This class must provide external static methods to obtain its own instances;
1.2. Application scenario
In the book graphic design mode, the usage scenario of single example mode in development is introduced in detail, as follows:
There can be multiple print tasks in a system, but there can only be one working task; A system can only have one window manager or file system; A system can only have one timing tool or ID (sequence number) generator
1.2. code implementation
Hungry Han formula (static variable)
- Class constructor private outside (prevent external use, can new an instance)
- Define a static variable inside the class and create the instance inside the class
- Provide a static public method to return an instance of this class
public class Singleton { private Singleton() {} private static final Singleton singleton = new Singleton(); public static Singleton getInstance() { return singleton; } }
Java
Advantages: the code implementation is simple. The instantiation of the class is completed when the class is loaded, avoiding the problem of thread synchronization.
Disadvantages: the instantiation is completed when the class is loaded, which does not achieve the effect of lazy loading. If this instance is not used, it will cause a waste of memory.
Hungry Chinese style (static code block)
public class Singleton { private Singleton() {} private static final Singleton singleton; static { singleton = new Singleton(); } public static Singleton getInstance() { return singleton; } }
Java
Using static code blocks to instantiate classes has the same advantages and disadvantages as using static variables.
Lazy (thread unsafe)
public class Singleton { private Singleton() {} private static Singleton singleton; public static Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
Java
Note: this implementation method is not recommended. Although it achieves the effect of lazy loading, it can only be used in single thread, and there is a thread safety problem in multithreading.
Lazy (thread safety, synchronization method)
public class Singleton { private Singleton() {} private static Singleton singleton; public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
Java
Note: this implementation method is also not recommended. Although it solves the thread safety problem, it uses the huge thing of synchronized, which makes the efficiency too low. Every time the getInstance() method is executed, the method synchronization must be carried out.
Lazy (thread unsafe, synchronous code block)
public class Singleton { private Singleton() { } private static Singleton singleton; public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { singleton = new Singleton(); } } return singleton; } }
Java
Note: the implementation method of synchronous code block is improved on the synchronous method. Because the efficiency of using synchronous method is very low, it is changed to synchronous code block, but this implementation method can not solve the problem of thread safety. Therefore, it is not recommended in practical development.
Double check (recommended)
public class Singleton { private Singleton() { } private static volatile Singleton singleton = null; public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
Java
Note: thread safety, delayed loading, high efficiency, recommended
The instantiation code is executed only once. When accessing again later, judge if (singleton == null) and return the instantiated object directly to avoid repeated method synchronization.
Static internal class (thread safe, recommended)
public class Singleton { private Singleton() { } private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
Java
- This method adopts the mechanism of class loading to ensure that there is only one thread when initializing the instance.
- The static internal class method does not instantiate the Singleton class immediately when it is loaded. Instead, when instantiation is needed, call the getInstance method to load the Singleton class, so as to complete the instantiation of Singleton.
- The static properties of the class will only be initialized when the class is loaded for the first time, so here, the JVM helps us ensure the safety of threads. When the class is initialized, other threads cannot enter.
- It avoids thread insecurity and realizes delayed loading by using the characteristics of static internal classes. It is highly efficient and recommended.
Enumeration (recommended)
public enum SingletonEnum { INSTANCE; public void method() { } }
Java
SingletonEnum instance = SingletonEnum.INSTANCE;
Java
Note: it can not only avoid the problem of multi-threaded synchronization, but also prevent deserialization and re creation of new objects. Disadvantage: it cannot be loaded lazily.