Single case mode summary

Keywords: Java Design Pattern Singleton pattern

Singleton mode

Singleton Pattern is a creation pattern. It involves a single class that is responsible for creating its own objects and ensuring that only one object is created. This class provides a unique way to access objects, which can be accessed directly without instantiating the objects of this class.

Attention

  • A singleton class can consist of only one instance
  • A singleton class must create its own unique instance
  • But without i, you must provide this instance to all objects

Intent: ensure that a class has only one instance and provide a global access point to access it

Main solution: frequent creation and destruction of a globally used class

advantage:

  • There is only one single instance in memory, which reduces the memory overhead, especially the frequent creation and destruction of instances
  • Avoid multiple occupation of resources, such as file operation

Disadvantages:

  • There is no interface and cannot be inherited. It conflicts with a single responsibility. A class only cares about the internal logic and does not care about how to instantiate externally
public class SingleObject {
 
   //Create an object of SingleObject
   private static SingleObject instance = new SingleObject();
 
   //Make the constructor private so that the class will not be instantiated
   private SingleObject(){}
 
   //Gets the only available object
   public static SingleObject getInstance(){
      return instance;
   }
 
   public void showMessage(){
      System.out.println("Hello World!");
   }
}
public class SingletonPatternDemo {
   public static void main(String[] args) {
 
      //Illegal constructor
      //Compile time error: constructor SingleObject() is not visible
      //SingleObject object = new SingleObject();
 
      //Gets the only available object
      SingleObject object = SingleObject.getInstance();
 
      //display messages
      object.showMessage();
   }
}

Several implementation methods of singleton mode

1. Lazy, thread unsafe

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

2 lazy, thread safe, static inner class

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

3. Hungry Han style

This method is easy to generate garbage objects'

Advantages: without locking, the execution efficiency will be much higher

Disadvantages: class initialization is performed when loading, which wastes memory

It is based on the classloader mechanism to avoid the problem of multi-threaded synchronization. However, instance is instantiated when the class is loaded. Although there are many reasons for class loading, most of them call getInstance methods in the singleton mode, it is uncertain that there are other ways (or other static methods) to cause class loading, At this time, initializing instance obviously does not achieve the effect of lazy loading.

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

4. Double check lock lazy type

When double checking, volatile must be added, which can prohibit the rearrangement of instructions. Otherwise, when creating an object with new, you may get a semi encapsulated object.

Assuming that there is no volatile keyword, both threads A and B call the singleton method for the first time. Thread A first executes instance = new Instance(). This construction method is A non atomic operation. After compilation, multiple bytecode instructions are generated. Due to the reordering of JAVA instructions, the assignment operation of instance may be executed first, In fact, this operation only opens up an area in memory to store objects and directly returns the memory reference. After that, the instance is not empty, but the actual initialization operation has not been executed. If thread B enters at this time, it will see an instance object that is not empty but incomplete (initialization has not been completed), so the volatile keyword needs to be added, Prohibit instruction reordering optimization, so as to safely implement singleton.

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

Posted by herrin on Tue, 23 Nov 2021 11:28:05 -0800