1. Introduction of singleton mode
The singleton pattern is one of the most widely used patterns, and can be said to be the only design pattern that junior engineers can use. When applying this pattern, the class of a singleton object must ensure that only one instance exists. In many cases, the whole system only needs one global object, which helps us coordinate the overall behavior of the system. For example, in an application, there should be only one instance of ImageLoader, which contains thread pools, caching systems, network requests, etc. It consumes resources, so there is no reason for it to have multiple instances. This is the use scenario of the singleton pattern.
2. Definition of singleton pattern
Ensure that the class has only one instance and instantiates itself and provides this instance to the entire system
3. Use scenarios
Scenarios to ensure that a class has only one object
4. UML Class Diagram
slightly
5. Multiple Realizations of Singleton Patterns
(1) Hungry Han Model
This is the simplest way to write the singleton pattern. Before we introduce it in detail, we will write a simple example, which will also facilitate other writings of the singleton pattern.
For example, a company has only one CEO, several VP s, and countless employees. The example is simple. Here's a little bit of implementation
General Staff Class: Staff.java
package com.example.singleton;
public class Staff {
public void work()
{
//work
}
}
VP.java
package com.example.singleton;
public class VP extends Staff {
@Override
public void work() {
// TODO Auto-generated method stub
super .work();
//Manage the following managers
}
}
CEO class: CEO.java
package com.example.singleton;
public class CEO extends Staff {
private static final CEO mCeo= new CEO();
// Privatization of constructors (privatization of constructors is the core of the singleton pattern)
private CEO() {
}
/**
* Method 1
* The Single Case Model of Hungry Man
*
* @author HP
*
*/
public static CEO getCeo () {
return mCeo ;
}
@Override
public void work() {
// TODO Auto-generated method stub
super .work();
// Managing vp
}
}
Company category: Company.java
package com.example.singleton;
import java.util.ArrayList;
import java.util.List;
/**
* Company category
* @author HP
*
*/
public class Company {
private List<Staff> allStaffs=new ArrayList<>();
public void addStaff(Staff per)
{
allStaffs.add(per);
}
public void showAllStaffs()
{
for(Staff per:allStaffs)
{
System.out.println("Obj:"+per.toString());
}
}
}
Finally, Main.java
package com.example.singleton;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Company cp = new Company();
//Method 1: Hungry Han Model
Staff ceo1 = CEO. getCeo();
Staff ceo2 = CEO. getCeo();
cp.addStaff(ceo1);
cp.addStaff(ceo2);
cp.showAllStaffs();
System. out .println("--------------------------------------" );
//The test found that two pieces of data are the same, indicating that the singleton class can only provide one object.
Staff vp1= new VP();
Staff vp2= new VP();
Staff staff1= new Staff();
Staff staff2= new Staff();
Staff staff3= new Staff();
cp.addStaff(vp1);
cp.addStaff(vp2);
cp.addStaff(staff1);
cp.addStaff(staff2);
cp.addStaff(staff3);
cp.showAllStaffs();
}
}
Output results:
Obj:com.example.singleton.CEO@1cacd5d4
Obj:com.example.singleton.CEO@1cacd5d4
--------------------------------------
Obj:com.example.singleton.CEO@1cacd5d4
Obj:com.example.singleton.CEO@1cacd5d4
Obj:com.example.singleton.VP@170a6001
Obj:com.example.singleton.VP@2a24ed78
Obj:com.example.singleton.Staff@5e6276e5
Obj:com.example.singleton.Staff@126be4cc
Obj:com.example.singleton.Staff@697a1686
That's the whole story of this example, where CEO.java is a singleton class, because as I said before, a company has only one CEO. As you can see from the code, the CEO class cannot construct objects through the new keyword because the constructor has been privatized. Objects can only be obtained by getCeo method, which is open to the CEO class, and this object is initialized at the time of declaration, which guarantees the uniqueness of the object. The above singular pattern is the so-called hungry man pattern.
(2) Lazy Man Model
The difference between the lazy mode and the hungry mode is that the object of the lazy mode is initialized when the getInstance method is called. The implementation of the Lazy Man Model is as follows: modify the CEO class.
package com.example.singleton;
public class CEO extends Staff {
// private static final CEO mCeo=new CEO();
private static CEO mCeo;
// Privatization of constructors (privatization of constructors is the core of the singleton pattern)
private CEO() {
}
// /**
// * Method 1
// * The Single Case Model of Hungry Man
// *
// * @author HP
// *
// */
// public static CEO getCeo() {
// return mCeo;
// }
/**
* Method two
* Slacker mode
* @return
*/
public static synchronized CEO getInstance() {
if (mCeo != null) {
mCeo = new CEO();
}
return mCeo ;
}
@Override
public void work() {
// TODO Auto-generated method stub
super .work();
// Managing vp
}
}
Corresponding modifications to Main.java
package com.example.singleton;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Company cp = new Company();
// // Method 1: Hungry Han Model
// Staff ceo1 = CEO.getCeo();
// Staff ceo2 = CEO.getCeo();
//Method 2: Lazy Man Model
Staff ceo1 = CEO. getInstance();
Staff ceo2 = CEO. getInstance();
cp.addStaff(ceo1);
cp.addStaff(ceo2);
cp.showAllStaffs();
System. out .println("--------------------------------------" );
//The test found that two pieces of data are the same, indicating that the singleton class can only provide one object.
Staff vp1= new VP();
Staff vp2= new VP();
Staff staff1= new Staff();
Staff staff2= new Staff();
Staff staff3= new Staff();
cp.addStaff(vp1);
cp.addStaff(vp2);
cp.addStaff(staff1);
cp.addStaff(staff2);
cp.addStaff(staff3);
cp.showAllStaffs();
}
}
The synchronized keyword is added to the getInstance method in the lazy man mode, that is to say, getInstance is a synchronized method, which is a means to ensure the uniqueness of objects in the case of multi-threading. However, there is a problem that even though mCeo has been initialized, the getInstance method is synchronized every time it is called, which results in unnecessary waste of resources. This is also the biggest problem with the slacker model.
Advantages and disadvantages of lazy model
The advantage of the lazy mode is that the singleton can be initialized only when it is used, which saves resources to a certain extent. The disadvantage is that the response is slower when it is first loaded. The biggest problem is that the getInstance method should be synchronized every time it is called, which will cause unnecessary overhead.
(3) Implementation of DCL
This method can not only initialize instances when needed, but also ensure thread safety. It is different when calling getInstance method. Its implementation is as follows:
package com.example.singleton;
public class CEO extends Staff {
// private static final CEO mCeo=new CEO();
private static CEO mCeo;
// Privatization of constructors (privatization of constructors is the core of the singleton pattern)
private CEO() {
}
// /**
// * Method 1
// * The Single Case Model of Hungry Man
// *
// * @author HP
// *
// */
// public static CEO getCeo() {
// return mCeo;
// }
// /**
// * Method two
// * Slacker mode
// * @return
// */
// public static synchronized CEO getInstance() {
// if (mCeo == null) {
// mCeo = new CEO();
// }
// return mCeo;
// }
/**
* Method three
* DCL
*/
public static CEO getInstance() {
if (mCeo == null) {
synchronized (CEO.class ) {
if (mCeo == null) {
mCeo =new CEO();
}
}
}
return mCeo ;
}
@Override
public void work() {
// TODO Auto-generated method stub
super .work();
// Managing vp
}
}
This is not a recommended singleton pattern
(4) Static internal class implementation singleton pattern
Its realization is as follows:
package com.example.singleton;
public class CEO extends Staff {
// private static final CEO mCeo=new CEO();
// private static CEO mCeo;
// Privatization of constructors (privatization of constructors is the core of the singleton pattern)
private CEO() {
}
// /**
// * Method 1
// * The Single Case Model of Hungry Man
// *
// * @author HP
// *
// */
// public static CEO getCeo() {
// return mCeo;
// }
// /**
// * Method two
// * Slacker mode
// * @return
// */
// public static synchronized CEO getInstance() {
// if (mCeo == null) {
// mCeo = new CEO();
// }
// return mCeo;
// }
// /**
// * Method three
// * DCL
// */
// public static CEO getInstance() {
// if (mCeo==null) {
// synchronized (CEO.class) {
// if (mCeo==null) {
// mCeo=new CEO();
// }
// }
// }
// return mCeo;
// }
/**
* Method Four Static Inner Class Singleton Patterns (Recommended Singleton Patterns)
*
* @return
*/
public static CEO getInstance() {
return SinletonCEO. mCeo;
}
private static class SinletonCEO {
private static final CEO mCeo = new CEO();
}
@Override
public void work() {
// TODO Auto-generated method stub
super .work();
// Managing vp
}
}
mCeo is not initialized when the CEO class is first loaded, but only when the CEO's getInstance method is first called. Therefore, the first call to the getInstance method causes the virtual machine to load the Sinleton CEO class, which not only ensures thread safety, but also guarantees the uniqueness of the singleton object, and also delays the instantiation of the singleton. So this is a recommended single implementation.
(5) Other singleton implementations
There are also two ways to implement singletons. They are enumerating singletons and using containers to implement singleton patterns. Here is no more specific introduction, want to know the students can read "Android Source Code Design Pattern Analysis and Practical Warfare" art.
6 Summary
Whatever the way to implement the singleton pattern, their core is to privatize the constructor, and to obtain a unique instance by static method. In this process, we must ensure thread safety, prevent deserialization leading to the regeneration of instances and other issues.