23 patrones de diseño: patrón singleton [estilo hambriento, estilo perezoso, doble verificación, clase interna estática, enumeración]

Serie de articulos

23 patrones de diseño: el propósito de los patrones de diseño y los siete principios a seguir
23 patrones de diseño: modo singleton [hambriento, perezoso, doble verificación, clases internas estáticas, enumeración]
23 patrones de diseño: modo de fábrica [fábrica simple, método de fábrica, fábrica abstracta ]
23 modos de diseño: modo prototipo [clonar oveja, copia superficial, copia profunda]


Tipo de patrón de diseño

1. Modo de creación: modo singleton, modo de fábrica abstracto, modo de prototipo, modo de constructor, modo de fábrica;

2. Modo estructural: modo adaptador, modo puente, modo decoración, modo combinación, modo apariencia, modo peso mosca, modo agente;

3. Modo de comportamiento: modo de método de plantilla, modo de comando, modo de visitante, modo de iterador, modo de observador, modo de mediador, modo de nota, modo de intérprete, modo de estado, modo de estrategia, modo de cadena de responsabilidad.

Nota: La clasificación y el nombre de diferentes libros pueden ser diferentes. "Design Patterns" tiene un libro especial.

 

1. Modo singleton

El llamado modo singleton consiste en tomar un determinado método para garantizar que en todo el sistema de software, una determinada clase solo pueda tener una instancia de objeto y la clase solo proporcione un método (método estático) para obtener su instancia de objeto.

Por ejemplo, SessionFactory de MyBatis, actúa principalmente como proxy de las fuentes de almacenamiento de datos y se encarga de crear objetos Session. En circunstancias normales, solo necesitamos usar un objeto SessionFactory, por lo que es un modo singleton.

Hay cinco modos principales de singleton: estilo hambriento (subdividido en constantes estáticas y bloques de código estático), estilo perezoso (subdividido en subprocesos inseguros, métodos sincronizados, bloques de código sincronizados), doble verificación, clases internas estáticas, enumeraciones

 

Chino hambriento

Método de variable estática

public class SingletonTest01 {
    
    
    public static void main(String[] args) {
    
    
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);//结果为true,两个对象相同
    }
}
//饿汉式(静态变量)
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static final Singleton instance = new Singleton();
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }
    //3. 对外提供唯一一个公共静态方法,来获得该类对象
    public static Singleton getInstance(){
    
    
        return instance;
    }
}

Ventajas y desventajas:

  1. Ventajas: El método de escritura es simple y la instanciación se completa cuando se carga la clase, evitando problemas de sincronización de subprocesos.
  2. Desventajas: se crea una instancia cuando se carga la clase, y no se logra el efecto de la carga diferida (la instancia se crea solo cuando se usa, de lo contrario no se crea. Si esta instancia no se ha usado, causará un desperdicio de memoria)
  3. Conclusión: este modo singletonDisponible, peromayoCausa una pérdida de memoria.

 

Bloque de código estático

public class SingletonTest02 {
    
    
    public static void main(String[] args) {
    
    
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2);//结果为true,两个对象相同
    }
}

//饿汉式(静态代码块)
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static Singleton instance;
    //在静态代码块里实例化
    static {
    
    
        instance = new Singleton();
    }
    
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }
    //3. 对外提供唯一一个公共静态方法,来获得该类对象
    public static Singleton getInstance(){
    
    
        return instance;
    }
}

Ventajas y desventajas: Lo mismo que el método de variable estática, excepto que la instanciación de la clase se coloca en el bloque de código estático, pero aún se instancia cuando se carga la clase.

 

Hombre flojo

Subproceso inseguro

//饿汉式(静态代码块)
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static Singleton instance;
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }
    //3. 对外提供唯一一个公共静态方法,来获得该类对象。当使用到该方法时,才创建对象。
    public static Singleton getInstance(){
    
    
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

Ventajas y desventajas:

  1. Puede reproducir un efecto de carga diferida (solo se creará cuando se use la instancia), pero solo se puede usar en un solo hilo.
  2. En el subproceso múltiple, si un subproceso ha entrado en el if, pero aún no se ha ejecutado nuevo, y otro subproceso está haciendo un juicio if, esto puede hacer que el primer subproceso tenga éxito en nuevo y el segundo subproceso ingrese si, entonces el segunda instancia de nuevo. Esto destruye el patrón singleton.
  3. Conclusión: no utilice este método en el desarrollo real .

 

Método de sincronización

//懒汉式(同步方法)
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static Singleton instance;
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }
    //3. 对外提供唯一一个公共静态方法,来获得该类对象
    //改为同步方法 synchronized
    public static synchronized Singleton getInstance(){
    
    
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

Ventajas y desventajas:

  1. Resuelve el problema de la inseguridad del hilo.
  2. La eficiencia es demasiado baja. Cuando cada hilo quiere obtener una instancia de clase, debido al sincronizado, debe estar sincronizado (esperando que se agote el proceso que usa este método). Sin embargo, este método solo necesita sincronizarse en el momento de la instanciación, y luego solo regresa a la instancia, sin sincronización.
  3. Conclusión: en el desarrollo real, no se recomienda su uso.

 

Bloque de código de sincronización

//懒汉式(同步方法)
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static Singleton instance;
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }
    //3. 对外提供唯一一个公共静态方法,来获得该类对象
    //改为同步代码块
    public static synchronized Singleton getInstance(){
    
    
        if (instance == null){
    
    
            synchronized(Singleton.class){
    
    
                instance = new Singleton();
            }
        }
        return instance;
    }
}

Este método ni siquiera resuelve la seguridad de subprocesos, porque cuando el primer subproceso es nuevo, el segundo subproceso todavía puede pasar el juicio if, y luego todavía nuevo.

 

Doble verificación

//双重检查
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static volatile Singleton instance;
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }
    //3. 对外提供唯一一个公共静态方法,来获得该类对象
    //加入双重检查代码,解决线程安全和懒加载问题,同时保证了效率
    public static Singleton getInstance(){
    
    
        if (instance == null){
    
    
            synchronized (Singleton.class){
    
    
                if (instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

 
Palabra clave volátil : La modificación de una variable volátil por un hilo será percibida inmediatamente por otros hilos, es decir, no habrá lectura sucia de datos, asegurando así la "visibilidad" de los datos.

Ventajas y desventajas:

  1. Double-Check se usa a menudo en el desarrollo de subprocesos múltiples. Hemos realizado dos juicios if en el código. Si hay tres subprocesos A, B y C, cuando tanto A como B pasan el primero if, A ingresa al bloque de código de sincronización Primero, sale después de la instanciación, y la instancia no es nula después de que B ingresa al bloque de código de sincronización, lo que garantiza la seguridad de los subprocesos. Sin embargo, el C subsiguiente no puede pasar el primer juicio if, por lo que el problema de eficiencia está resuelto.
  2. Obtenga seguridad de subprocesos, carga diferida y alta eficiencia.
  3. Conclusión: en el desarrollo real, se recomienda este patrón de diseño singleton.

 

Clase interna estática

//静态内部类
class Singleton{
    
    
    //1. 在该类内部创建实例对象
    private static volatile Singleton instance;
    //2. 构造器私有化,使外部不能通过new创建对象
    private Singleton(){
    
    }

    //3. 编写静态内部类
    private static class SingletonInstance{
    
    
        private static final Singleton INSTANCE = new Singleton();
    }

    //4. 对外提供唯一一个公共静态方法,来获得该类对象
    public static Singleton getInstance(){
    
    
        return SingletonInstance.INSTANCE;
    }
}

Ventajas y desventajas:

  1. Una de las características de las clases internas estáticas es que no se cargarán con la carga de clases externas, es decir, cuando se cargue Singleton, no se cargará SingletonInstance, y solo se cargará cuando se ejecute Singleton.INSTANCE, logrando así un efecto de carga diferida.
  2. Las propiedades estáticas de la clase solo se inicializarán cuando la clase se cargue por primera vez, por lo que aquí JVM nos ayuda a garantizar la seguridad de los subprocesos, porque otros subprocesos no pueden ingresar cuando se inicializa la clase.
  3. Obtenga seguridad de subprocesos, carga diferida y alta eficiencia.
  4. Conclusión: recomendado.

 

enumerar

package design_partten.singleton.type8;

public class SingletonTest08 {
    
    
    public static void main(String[] args) {
    
    
        Singleton singleton1 = Singleton.INSTANCE;
        Singleton singleton2 = Singleton.INSTANCE;
        System.out.println(singleton1 == singleton2);//结果为true,两个对象相同
        singleton1.sayOk();
    }
}

//静态内部类
enum Singleton{
    
    
    INSTANCE;
    public void sayOk(){
    
    
        System.out.println("ok~");
    }
}

Ventajas y desventajas:

  1. El uso de la enumeración agregada en JDK1.5 para implementar el modo singleton no solo puede evitar problemas de sincronización de múltiples subprocesos, sino también evitar que la deserialización vuelva a crear objetos.
  2. Conclusión: recomendado.

 

Uso del código fuente JDK del modo singleton

Runtime es el modo singleton estilo hombre hambriento, porque puede garantizar que lo usaremos, por lo que no habrá pérdida de memoria, y también se puede garantizar la seguridad de los subprocesos.

1615209917646

 

resumen

  • El modo singleton garantiza que solo haya un objeto de esta clase en la memoria del sistema, lo que ahorra recursos del sistema. Para algunos objetos que deben crearse y destruirse con frecuencia, el uso del modo singleton puede mejorar el rendimiento del sistema.
  • Cuando desee crear una instancia de un objeto, debe recordar utilizar el método correspondiente para obtener el objeto en lugar de utilizar new.
  • Escenarios de uso del modo singleton: objetos que deben crearse y destruirse con frecuencia; objetos que requieren demasiado tiempo o recursos para crear objetos, pero deben usarse con frecuencia; objetos de herramientas; objetos que acceden con frecuencia a bases de datos o archivos (como data) Fuente, SessionFactory).

Supongo que te gusta

Origin blog.csdn.net/qq_39763246/article/details/114553165
Recomendado
Clasificación