3. Singleton design pattern

I believe everyone knows design patterns, and the one you hear most should be the singleton design pattern. This pattern is also the most used design pattern in development. There may be many people who will write several design patterns, so do you know what is Design Patterns? Why is there a singleton design pattern, that is, what is its role? What are the ways to write singleton mode? For such questions, some children's shoes may not be able to answer very well. It’s okay to study the singleton design pattern in detail with you today. I believe that you will have a detailed understanding of the singleton design pattern by studying this article. If you have any errors, you are welcome to criticize and correct. If you have any questions, please leave a message.

By this blog you will learn the following
① What is a design pattern
② Why Singleton design pattern that is its usefulness, and it solves the problem
③ how to achieve a single case, that is, its design is what
④ singleton What are the ways to write the
pattern ⑤What matters should be paid attention to in the interview of the singleton pattern

1. What is a design pattern?

  First of all, let’s look at the first question. What is a design pattern? Its definition in Baidu Encyclopedia is as follows: Design pattern is a set of repeatedly used, most people know, classified and cataloged, a summary of code design experience. (Baidu Encyclopedia)
In fact, the design pattern is the product of people's practice. In the initial development process, many people found repeated code writing. Those developers who continued to summarize and extract were finally recognized by everyone, so the design came out Patterns, in fact, the types of design patterns can be divided into about 23 kinds. Today, I will mainly study the singleton design pattern with everyone, because this design pattern is the most used design pattern. In future articles, we will bring discussion of other modes.

2. Why is there a singleton design pattern?

We all know that the singleton pattern is the most used design pattern in development, so why is there a singleton design pattern? For this problem, I believe that many people who can write singletons will have this question. Let me first talk about the use of singletons, and then give an example, everyone will understand why there are singletons. The singleton mode is mainly to avoid waste of resources due to the creation of multiple instances, and multiple instances may cause errors in the results due to multiple calls. Using the singleton mode can ensure that there is only one instance in the entire application. From its name, we can see that the so-called singleton is a single instance, that is to say, the problem it can solve is: it can guarantee the uniqueness of objects of a class in memory, in some commonly used tool classes, thread pools, and caches. , Database, account login system, configuration files and other programs may only allow us to create one object. On the one hand, creating multiple objects may cause program errors, on the other hand, creating multiple objects may also cause waste of resources. On this basis, the singleton design pattern came into being because the use of singletons can ensure that there is only one instance in the entire application. You may be a little confused to see this, it doesn’t matter, let’s give an example. I believe you will It will be very clear why there is a singleton.

If one has such a requirement, there is a class A and a class B that share the information of the configuration file. There are a lot of data in this configuration file as shown in the figure below

Insert picture description here

As shown in the figure above, there are shared data Num1, Num2, Num3, etc. in the class ConfigFile. If you modify the data in ConfigFile in class A, there should be the following code in class A

ConfigFile configFile=new ConfigFile();
configFile. Num1=2;

At this time Num1=2 in configFile, but please note that here is new ConfigFile is an object, imagine the following operations in class B after the above operations

ConfigFile configFile=new ConfigFile();
System. out.println("configFile.Num1=" +configFile.Num1);

That is, directly new ConfigFile(); and then print Num1. Think about the data printed at this time? I think you should know that it prints the result like this: configFile.Num1=1; that is to say, because each call creates a ConfigFile object, the modification in class A does not really change the ConfigFile Value, it only changes the value of the object created in class A. If now it is required to modify the data in class A, class B should be notified, that is, the data operated in class A and class B is the same data, and class A changes a data, class B will also get this data, and in class A The operation is performed on the modified basis, so what should we do? Seeing this, everyone may say easy, isn’t it OK to set the data in ConfigFile to static? Yes, it is good to have this idea, and there is nothing wrong with it. But we all know that the life cycle of static data is very long. If there is a lot of data in ConfigFile, if all of them are set to static, it will be a great loss of memory. Therefore, although it is feasible to set all to static, it is not a good solution. So what should we do? To solve the above problem, it is not difficult. As long as the object can be guaranteed to be unique, the above problem can be solved. Then the question is how to ensure the uniqueness of the object? So you need to use the singleton design pattern.

3. The design idea of ​​singleton mode

We mentioned above that the key to solving the problem now is to ensure that there is only one object in the application, so how to ensure that there is only one object?
In fact, it only takes three steps to ensure the uniqueness of the object

(1) Other programs are not allowed to use the new object.

Because new is to open up new space, changing the data here only changes the data of the created object. If it can be new, every new object will be generated, which certainly cannot guarantee the uniqueness of the object.

(2) Create objects in this class
because other programs are not allowed to new objects, so the objects here need to be new in this class

(3) Provide a method for other programs to obtain the object

Because the object is created in this class, it is necessary to provide a method for other classes to obtain this object.

So how do these three steps be implemented in code? Convert the above three steps into a code description like this

(1) privatize the constructor of
this class (2) create an object of this class in this class through new
(3) define a public method to return the object created in this class

4. How to write singleton mode

After the analysis in 3, we understand the problem solved by the singleton and its realization idea, and then take a look at its implementation code, the writing of the singleton pattern can be divided into 5 kinds and 5 kinds ①lazy man ②hungry man Formula ③double check lock ④static inner class ⑤enumeration. Next, let's take a look at the code implementation of these several singleton design patterns, and their advantages and disadvantages

4.1 Hungry Chinese in Singleton Mode [Available]

public class Singleton {
 
	private static Singleton instance=new Singleton();
	private Singleton(){};
	public static Singleton getInstance(){
		return instance;
	}
}

interview method

Singleton instance = Singleton.getInstance();

得到这个实例后就可以访问这个类中的方法了。

Advantages: From its implementation, we can see that the implementation of this method is relatively simple, and the instantiation is completed when the class is loaded, avoiding thread synchronization problems.

Disadvantages: Since it is instantiated when the class is loaded, it does not achieve the effect of Lazy Loading, which means that I may not use this instance, but it

It will also be loaded, which will cause a waste of memory (but this waste can be ignored, so this method is also recommended).

4.2 Hungry Chinese style transformation of singleton mode [available]

public class Singleton{

  private static Singleton instance = null;
  
  static {
  	instance = new Singleton();
  }

  private Singleton() {};

  public static Singleton getInstance() {
  	return instance;
  }
}

interview method:

Singleton instance = Singleton.getInstance();

得到这个实例后就可以访问这个类中的方法了。

You can see that the above code is implemented in accordance with the three steps analyzed in 2. The writing method is called the hungry style because it has already instantiated the object when the class is created. In fact, 4.2 and 4.1 are just a bit different in writing. Objects are created when the class is initialized. Its advantages and disadvantages are the same as 4.1, which can be classified as one writing.

4.3 The lazy style of singleton mode [thread is not safe and unavailable]

public class Singleton {
 
	private static Singleton instance=null;
	
	private Singleton() {};
	
	public static Singleton getInstance(){
		
		if(instance==null){
			instance=new Singleton();
		}
		return instance;
	}
}

This method creates the object when the getInstance method is called, so it is lazy and is called lazy.
In the above two ways of writing, the lazy man actually has thread safety problems. Students who like to root the problem may ask, what kind of thread safety problems exist? How did it cause this problem? Okay, let's talk about under what circumstances this writing will have problems. There may be such a situation in the running process: there are multiple threads to call the getInstance method to obtain the instance of Singleton, then such a situation may occur when the first thread is executing if (instancenull) this statement, at this time instance is the entry statement for null. When instance=new Singleton() has not been executed (instance is null at this time), the second thread also enters if(instancenull) This statement, because the thread that entered this statement before has not executed instance=new Singleton(), so it will execute instance=new Singleton() to instantiate the Singleton object, because the second thread also entered the if statement. It will also instantiate Singleton objects. This led to the instantiation of two Singleton objects. So the lazy man of the singleton mode has thread safety problems. Since it has problems, there may be a way to solve this problem, so how to solve it? For this kind of problem, many people may think of locking, so the following wording appeared.

4.4 Lazy-style thread-safe [thread safety, low efficiency is not recommended]


public class Singleton {
 
	private static Singleton instance=null;
	
	private Singleton() {};
	
	public static synchronized Singleton getInstance(){
		
		if(instance==null){
			instance=new Singleton();
		}
		return instance;
	}
}

Disadvantage: The efficiency is too low. When each thread wants to obtain an instance of the class, the execution of the getInstance() method must be synchronized. In fact, this method is enough to execute the instantiation code only once. If you want to obtain an instance of this class later, just return directly. The method of synchronization efficiency is too low to be improved.
4.5 Singleton mode lazy style [thread is not safe, unavailable]
For the improvement of the above defects, some people may think of the following code

public class Singleton7 {
 
	private static Singleton instance=null;
	
	public static Singleton getInstance() {
		if (instance == null) {
			synchronized (Singleton.class) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}

In fact, this writing method is thread-unsafe like 4.3. When a thread has not instantiated Singleton, another thread will enter the if statement when it reaches the judgment statement if (instance==null). Although the lock is added, When the first thread finishes executing instance=new Singleton() and jumps out of the lock, another thread that enters the if statement will also instantiate another Singleton object. The principle of thread insecurity is similar to 4.3. Therefore, this improvement method is not feasible. After the great gods have explored step by step, they have written a lazy double check lock.

4.6 Singleton mode lazy double check lock [recommended]

public class Singleton {
	/**
	 * 懒汉式变种,属于懒汉式中最好的写法,保证了:延迟加载和线程安全
	 */
	private static Singleton instance=null;
	
	private Singleton() {};
	
	public static Singleton getInstance(){
		 if (instance == null) {  
	          synchronized (Singleton.class) {  
	              if (instance == null) {  
	            	  instance = new Singleton();  
	              }  
	          }  
	      }  
	      return instance;  
	}
}

interview method

Singleton instance = Singleton.getInstance();

得到这个实例后就可以访问这个类中的方法了。

The concept of Double-Check is not unfamiliar to multi-threaded developers. As shown in the code, we have performed two if (instance== null) checks to ensure thread safety. In this way, the instantiation code only needs to be executed once, and when it is accessed again later, it will judge if (instance== null) and directly return the instantiated object.

Advantages: thread safety; lazy loading; higher efficiency.

4.7 Internal category [Recommended]

public class Singleton{
 
	
	private Singleton() {};
	
	private static class SingletonHolder{
		private static Singleton instance=new Singleton();
	} 
	
	public static Singleton getInstance(){
		return SingletonHolder.instance;
	}
}

interview method

Singleton instance = Singleton.getInstance();

得到这个实例后就可以访问这个类中的方法了。

   This method is similar to the mechanism adopted by the Hungry Chinese method, but it is different. Both use a class loading mechanism to ensure that there is only one thread when initializing an instance. different

The place in the hungry Chinese style is that as long as the Singleton class is loaded, it will be instantiated, without the effect of Lazy-Loading, and the static inner class method is when the Singleton class is loaded

It will not be instantiated immediately, but when instantiation is needed, the getInstance method will be called to load the SingletonHolder class 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, JVM helps us to ensure the safety of the thread. When the class is initialized, other threads are

Inaccessible.

Advantages: avoid thread insecurity, delayed loading, and high efficiency.

4.8 Enumeration [Highly recommended]

public enum SingletonEnum {
	
	 instance; 
	 
	 private SingletonEnum() {}
	 
	 public void method(){
	 }
}

interview method

SingletonEnum.instance.method();

You can see that the writing of enumeration is very simple, and the access is also very simple. Here SingletonEnum.instance The instance here is the reference of the SingletonEnum type, so you can call the method in the enumeration when you get it.

Use the enumeration added in JDK1.5 to realize the singleton mode. Not only can avoid multi-thread synchronization problems, but also prevent deserialization from recreating new objects. It may be that enumeration was added in JDK1.5, so in actual project development, few people have written this way. This method is also the best way. It is recommended if the JDK meets the requirements during development. Use this way.

5. Summary

In the real project development, generally use 4.1, 4.6, 4.7, 4.8 to see which way of writing you like the most. Under normal circumstances, there is no problem with these modes. In order to force me to use 4.6, we often use The Android-Universal-Image-Loader open source project also uses 4.6. In fact, the safest way to write is 4.8, which is enumeration. Its implementation is very simple and the most secure is perfect, but it may be because it only supports JDK1. 5. Or maybe because enumeration is not familiar to everyone, not many people currently use it, but you can try it. In addition, when we use the reflection mechanism, the uniqueness of the instance may not be guaranteed, but the enumeration can always guarantee the uniqueness. Please refer to the blog for details: http://blog.csdn.net/java2000_net/article/details/3983958 but in general This is rarely encountered under the circumstances.

6. Questions in the interview in singleton mode

 The singleton mode is often encountered in interviews, because it is a test of the solidity of a programmer's foundation. If you tell the interviewer that you have done a project, the interviewer asks you to write a few singleton designs If you can’t write the model, do you think the interviewer will believe it? During the interview, you must carefully prepare for each interview. Even if you are admitted, you are very likely to be dissatisfied with the company. Okay, let’s get back to the subject. In fact, few people in the singleton design pattern will ask in the interview Chinese writing methods generally ask about the lazy-style thread safety of the singleton design pattern, so everyone must fully understand the thread safety of the singleton pattern. Take time for these patterns, learn thoroughly, and encounter them in the interview. You will not be afraid of any questions about singleton mode, right?

如果发现博客中有任何问题或者您还有什么疑问欢迎留言,您的支持是我前进的动力
If this blog is helpful to you, please like or leave a comment

Please indicate the source for reprinting: http://blog.csdn.net/dmk877/article/details/50311791

Reference blog:
https://segmentfault.com/q/1010000003732558

http://tianweili.github.io/blog/2015/03/02/singleton-pattern/

Guess you like

Origin blog.csdn.net/GTC_GZ/article/details/108742184