Singleton mode (implemented in Java code)

There are 23 types of design patterns:

  • Creation mode: singleton mode, abstract factory mode, prototype mode, builder mode, factory mode.
  • Structural mode: adapter mode, bridge mode, decoration mode, combination mode, appearance mode, flyweight mode, agent mode.
  • Behavioral mode: template method mode, command mode, visitor mode, iterator mode, observer mode, mediator mode, memo mode, interpreter mode (Interpreter mode), state mode, strategy mode, chain of responsibility mode (chain of responsibility mode).

After that, we will explain them one by one in the above order. First, let's look at the singleton mode:

1. Introduction to singleton design pattern

  • Ensure that a class has only one instance and provide a global access point to it.
  • That is to say, a certain method is taken to ensure that in the entire software system, there can only be one object instance for a certain class, and the class only provides a method (static method) to obtain its object instance.

Two. Eight realization methods of singleton design pattern

There are eight ways in singleton mode:

  • Hungry Chinese style (static attribute)
  • Hungry Chinese (static code block)
  • Lazy (unsafe thread)
  • Lazy (thread-safe, synchronous method)
  • Lazy (thread-safe, synchronized code blocks)
  • Double check
  • Static inner class
  • Enumeration
    Below we explain in order, first we look at the hungry Chinese style (static constant):

1. Hungry Chinese style (static attribute)

Proceed as follows:

  1. The constructor is privatized (to prevent new).
  2. Create objects inside the class.
  3. Expose a static public method.

Code demo:

public class SingletonMode01 {
    
    

    //1.构造器私有化 (防止 new )
    private SingletonMode01(){
    
    

    }

    //2.类的内部创建对象(静态属性)
    private static SingletonMode01 instance = new SingletonMode01();

    //3.向外暴露一个静态的公共方法。getInstance
    public static SingletonMode01 getInstance(){
    
    
        return instance;
    }

}

Advantages and disadvantages:

  • Advantages: This writing method is relatively simple, that is, instantiation is completed when the class is loaded. Avoid thread synchronization problems.
  • Disadvantages: The instantiation is completed when the class is loaded, which does not achieve the effect of Lazy Loading. If this instance is never used from start to finish, it will cause a waste of memory.

This singleton mode is available, which may cause a waste of memory

2. Hungry Chinese style (static code block)

Proceed as follows:

  • The same as 1 is to execute in the static code block when assigning a static constant

Code demo:

public class SingletonMode02 {
    
    
    //1.构造器私有化 (防止 new )
    private SingletonMode02(){
    
    

    }

    //2.类的内部创建对象(静态常量)
    private static SingletonMode02 instance;
    
    //在静态代码中对静态常量赋值
    static{
    
    
        instance = new SingletonMode02();
    }

    //3.向外暴露一个静态的公共方法。getInstance
    public static SingletonMode02 getInstance(){
    
    
        return instance;
    }
}

Pros and cons:

  • This method is similar to the above method, except that the process of class instantiation is placed in a static code block. When the class is loaded, the code in the static code block is executed to initialize the instance of the class. The advantages and disadvantages are the same as above.

This singleton mode is available, but it may cause a waste of memory

3. Lazy (thread insecure)

Code demo:

public class SingletonMode03 {
    
    
    
    private static SingletonMode03 instance; 
    
    private SingletonMode03(){
    
    
        
    }
    
    //当调用getInstance才创建单例对象,饿汉式
    public static SingletonMode03 getInstance(){
    
    
        if(instance == null){
    
    
             instance = new SingletonMode03();
        }
        return instance;
    }
}

Pros and cons:

  • It has the effect of Lazy Loading, but it can only be used under single thread.
  • If in multi-threading, one thread enters the if (instance == null) judgment statement block, and there is no time to execute it in the future, and another thread also passes the judgment statement, then multiple instances will be generated. Therefore, this method cannot be used in a multithreaded environment.

In actual development, do not use this method.

4. Lazy man style (thread safety, synchronization method)

Code demo:

public class SingletonMode04 {
    
    
    
    private static SingletonMode04 instance;
    
    private SingletonMode04(){
    
    
        
    }
    
    //加入了同步方法,解决线程不安全问题
    public static synchronized SingletonMode04 getInstance(){
    
    
        if(instance == null){
    
    
            instance = new SingletonMode04();
        }
        return instance;
    }
}

Pros and cons:

  • Solve the problem of thread insecurity
  • 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 is too inefficient for synchronization.

In actual development, this method is not recommended.

5. Lazy (thread-safe, synchronized code blocks)

public class SingletonMode05 {
    
    

    private static SingletonMode05 instance;

    private SingletonMode05 (){
    
    

    }

    //加入了同步代码块,解决线程不安全问题
    public static SingletonMode05 getInstance(){
    
    
        if(instance == null){
    
    
            synchronized (SingletonMode05.class){
    
    
                instance = new SingletonMode05();
            }
        }
        return instance;
    }
}

Advantages and disadvantages:

  • This method was originally intended to improve the fourth implementation method, because the previous synchronization method was too inefficient, so the instantiated code block was generated synchronously.
  • But this synchronization does not play a role in thread synchronization. Consistent with the situation encountered in the third implementation method, if a thread enters the if (instance == null) judgment statement block, and there is no time to execute it in the future, another thread also passes the judgment statement, then it will be generated Multiple instances

In actual development, this method cannot be used

6. Double check

public class SingletonMode06 {
    
    

    //volatile关键字:
    //1. 保证变量的可见性:当一个被volatile关键字修饰的变量被一个线程修改的时候,其他线程可以立刻得到修改之后的结果。
    //   当一个线程向被volatile关键字修饰的变量写入数据的时候,虚拟机会强制它被值刷新到主内存中。
    //   当一个线程用到被volatile关键字修饰的值的时候,虚拟机会强制要求它从主内存中读取。
    //2. 屏蔽指令重排序:指令重排序是编译器和处理器为了高效对程序进行优化的手段;
    //   它只能保证程序执行的结果时正确的,但是无法保证程序的操作顺序与代码顺序一致。
    //   这在单线程中不会构成问题,但是在多线程中就会出现问题。
    //   非常经典的例子是在单例方法中同时对字段加入voliate,就是为了防止指令重排序。
    private static volatile SingletonMode06 instance;

    private SingletonMode06() {
    
    

    }

    //使用双重检查
    public static SingletonMode06 getInstance() {
    
    
        if(instance == null){
    
    
            synchronized (SingletonMode06.class){
    
    
                if(instance == null){
    
    
                    instance = new SingletonMode06();
                }
            }
        }
        return instance;
    }
}

Advantages and disadvantages:

  • The concept of Double-Check is often used in multithreaded development. 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, which also avoids repeated method synchronization.
  • This method is thread safe; lazy loading; higher efficiency

In actual development, it is recommended to use this singleton design pattern

7. Static inner class

public class SingletonMode07 {
    
    

    private SingletonMode07(){
    
    

    }

    private static class SingletonModeInstance{
    
    
        private static final SingletonMode07 INSTANCE = new SingletonMode07();
    }

    public static SingletonMode07  getInstance(){
    
    
        return SingletonModeInstance.INSTANCE;
    }
}

Advantages and disadvantages:

  • This method uses a class loading mechanism to ensure that there is only one thread when initializing an instance.
  • In the static internal class method, INSTANCE will not be instantiated immediately when the SingletonMode07 class is loaded, but when instantiation is needed, the getInstance method will be called to load the SingletonModeInstance class, thus completing the instantiation of SingletonMode07.
  • 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 to ensure the safety of the thread. When the class is initialized, other threads cannot enter.
  • This method avoids thread insecurity, uses the characteristics of static internal classes to implement lazy loading, and is highly efficient

This method is recommended.

8. Enumeration

public enum SingletonMode08 {
    
    
    
    INSTANCE("单例模式",123456);

    private String name;
    private int number;

    SingletonMode08(String name, int number) {
    
    
        this.name = name;
        this.number = number;
    }

    @Override
    public String toString() {
    
    
        return "SingletonMode08{" +
                "name='" + name + '\'' +
                ", number=" + number +
                '}';
    }
}

Pros and cons:

  • This uses the enumeration added in JDK1.5 to implement the singleton mode. Not only can avoid multi-thread synchronization problems, but also prevent deserialization from re-creating new objects.
  • This method is advocated by Effective Java author Josh Bloch

This way is recommended

3. Summary of Singleton Design Pattern

  • The singleton mode ensures that there is only one object of this class in the system memory, which saves system resources. For some objects that need to be created and destroyed frequently, the singleton mode can improve system performance
  • When you want to instantiate a singleton class, you must remember to use the corresponding method of obtaining the object instead of using new
  • Scenarios used in the singleton mode: objects that need to be created and destroyed frequently, too much time or resources are consumed when creating objects (ie: heavyweight objects), but frequently used objects, tool objects, frequent Objects that access databases or files (such as data sources, session factories, etc.)

Guess you like

Origin blog.csdn.net/MrYushiwen/article/details/112316230