Modo singleton del patrón de diseño de Android: el modo más utilizado

1. ¿Qué es el patrón singleton?

El modo singleton es para garantizar que solo haya una instancia de una determinada clase, instanciarla por sí misma y proporcionar esta instancia a todo el sistema. Al aplicar el patrón singleton, la clase del objeto singleton debe garantizar que solo exista una instancia. En muchos casos, todo el sistema solo necesita tener un objeto global, lo que nos ayudará a coordinar el comportamiento general del sistema.

En segundo lugar, el escenario de uso del modo singleton

Cuando los objetos no se pueden construir libremente, asegúrese de que una determinada clase tenga uno y solo un objeto para evitar varios objetos que consuman demasiados recursos, o solo debe haber uno y solo un objeto de cierto tipo. Por ejemplo, la creación de un objeto consume demasiados recursos. Si desea acceder a recursos como IO y base de datos, este es el modo singleton.

Tres, los puntos clave para realizar el modo singleton

1. El constructor no está abierto al mundo exterior, generalmente Privado,
al privatizar el constructor de la clase singleton, el código del cliente no puede construir manualmente el objeto de la clase singleton en forma de nuevo.
2. Devuelva el objeto de la clase singleton a través de un método estático o enumeración, la
clase singleton expondrá un método estático público, y el cliente debe llamar a este método estático para obtener el único objeto de la clase singleton.
3.Asegúrese de que haya uno y solo un objeto singleton, especialmente en un entorno multiproceso;
debe garantizar la seguridad de los subprocesos en el proceso de obtención de este objeto singleton , es decir, hay únicos y únicos objetos para construir un singleton en un entorno multiproceso Uno. (Es difícil de implementar)
4. Asegúrese de que el objeto singleton no se reconstruya durante la deserialización.

Cuatro, varios métodos de implementación del modo singleton

1. Modo de hombre hambriento

public class Singleton{
    private static final Singleton mInstance = new Singleton();
    // 构造函数私有
    private Singleton(){
    }
    // 公有的静态函数,对外暴露获取单例对象的接口
    public static Singleton getInstance(){
        return mInstance;
    }
}

El modo de hombre hambriento inicializa un objeto estático cuando se declara.

  1. Desventajas : el objeto se volverá a crear durante la deserialización.

2. Modo más holgazán

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

El modo perezoso es declarar un objeto estático e inicializarlo cuando el usuario llama a getInstance por primera vez.

  1. Ventajas : Solo se crearán instancias de singletons cuando se usen, lo que ahorra recursos hasta cierto punto;
  2. Desventajas : necesita instanciarse a tiempo cuando se carga por primera vez, y la respuesta es lenta, el objeto se volverá a crear durante la deserialización;
  3. El mayor problema : la palabra clave sincronizada se agrega al método getInstance (), por lo que cada vez que se llama a getInstance (), se realiza una sincronización, lo que provoca una sobrecarga de sincronización innecesaria;
  4. Conclusión : en general, no se recomienda el modo de hombre perezoso .

3. Double CheckLock (DCL) para lograr singleton (recomendado)

public class Singleton(){
    private volatile static Singleton mInstance = null;
    private Singleton(){
    }
    public void doSomething(){
        System.out.println("Do sth.");
    }
    public static Singleton getInstance(){
        if(mInstance == null){
            synchronized(Singleton.class){
                if(mInstance == null){
                    mInstance = new SIngleton();
                }
            }
        }
        return mInstance;
    }
}

Entre ellos, agregar la palabra clave volátil puede resolver el problema de falla de DCL, pero afectará más o menos el rendimiento, pero considerando la corrección del programa, vale la pena sacrificar este rendimiento.

  1. Ventajas : el singleton se puede inicializar solo cuando sea necesario, y la unicidad del objeto singleton se puede garantizar en la mayoría de los escenarios, y se puede garantizar la seguridad de los subprocesos. Después de inicializar el objeto singleton, se llama a getInstance sin bloqueo de sincronización. Alta utilización de recursos, el objeto singleton se instanciará cuando getInstance se ejecute por primera vez, lo cual es altamente eficiente;
  2. Desventajas : La respuesta es un poco más lenta la primera vez que se carga y ocasionalmente falla debido al modelo de memoria de Java. También hay ciertos defectos en un entorno de alta concurrencia, aunque la probabilidad de que ocurran es pequeña, el objeto se volverá a crear durante la deserialización;
  3. Conclusión : Además del complicado escenario de concurrencia o el caso de una versión inferior a JDK 6, el modo DCL es la implementación singleton más utilizada.

4. Modo singleton de clase interna estática (recomendado)

public class Singleton(){
    
    
    private Singleton(){
    }
    public static Singleton getInstance(){
        return SingletonHolder.mInstance;
    }
    /**
     * 静态内部类
     */
     private static class SingletonHolder(){
    
    
         private static final Singleton mInstance = new Singleton();
     }
}

Aunque DCL hasta cierto punto, resuelve el consumo de recursos, la sincronización redundante, la seguridad de subprocesos y otros problemas, pero en algunos casos habrá un problema de falla de bloqueo de doble verificación (DCL) , se recomienda utilizar un patrón de singleton de clases internas estáticas en su lugar.

  1. Ventajas : garantizar la seguridad de los subprocesos, garantizar la singularidad de los objetos singleton y retrasar la instanciación de singletons;
  2. Desventajas : el objeto se volverá a crear durante la deserialización ;
  3. Conclusión : se recomienda utilizar este método para implementar el modo singleton.

5. Enumeración singleton

public enum SingletonEnum{
    INSTANCE;
    public void doSomething(){
        System.out.println("Do sth.");
    }
}
  1. Ventajas: fácil de escribir; la creación de instancias de enumeración predeterminadas es segura para subprocesos; es un singleton en cualquier caso, incluso cuando se deserializa ;

6. Utilice contenedores para implementar el modo singleton

public class SingletonManager{ 
    private static Map<String,Object> objMap = new HashMap<String,Object>();
    private Singleton(){
    }
    public static void registerService(String key,Object mInstance){ 
        if(!objMap.containKey(key)){ 
            objMap.put(key,mInstance);
        }
    }
    public static ObjectgetService(String key){ 
        return objMap.get(key);
    }
}
  1. Ventajas : reducir el costo de uso del usuario, ocultar la implementación específica al usuario y reducir el grado de acoplamiento.

Cinco, resumen

  1. El principio básico : privatizar el constructor y obtener una instancia única a través de un método estático. Durante el proceso de adquisición, se debe garantizar la seguridad de los subprocesos para evitar que la deserialización genere objetos de instancia.

  2. Ventajas :
    (1) Dado que el modo singleton tiene solo una instancia en la memoria, el gasto de memoria se reduce, especialmente cuando un objeto debe crearse y destruirse con frecuencia, y el rendimiento no se puede optimizar durante la creación o destrucción. La ventaja del modo singleton es Obviamente;
    (2) Dado que el modo singleton solo genera una instancia, la sobrecarga de rendimiento del sistema se reduce. Cuando la generación de un objeto requiere más recursos, como leer la configuración y producir otros objetos dependientes, puede pasar Un objeto singleton se genera directamente cuando se inicia la aplicación y luego reside permanentemente en la memoria para resolverlo;
    (3) El modo singleton puede evitar la ocupación múltiple de recursos, como una operación de escritura de archivos, porque solo existe una instancia en la memoria. Evite las operaciones de escritura simultáneas en el mismo archivo de recursos;
    (4) El modo singleton puede establecer un punto de acceso global en el sistema para optimizar y compartir el acceso a los recursos. Por ejemplo, una clase singleton puede diseñarse para ser responsable del procesamiento de mapas de todas las tablas de datos.

  3. Desventajas :
    (1) El modo singleton generalmente no tiene interfaz, y es difícil de extender, excepto para modificar el código;
    (2) Si el objeto singleton contiene Contexto, es fácil causar pérdidas de memoria. En este momento, debe prestar atención a la información que se pasa al objeto singleton. El contexto es preferiblemente el contexto de la aplicación.

  4. Extensión :
    P: ¿Cómo evitar que los objetos singleton se regeneren cuando se deserializan en los ejemplos anteriores?
    R: A través de la serialización, un objeto de instancia singleton se puede escribir en el disco y luego volver a leerlo para obtener una instancia de manera efectiva. Incluso si el constructor es privado, ya es posible crear una nueva instancia de la clase de una manera especial durante la deserialización, lo que equivale a llamar al constructor de la clase. La operación de deserialización proporciona una función de enlace muy especial.La clase tiene un método privado, instanciado readResolve () , que permite a los desarrolladores controlar la deserialización del objeto.
    Los siguientes métodos se pueden agregar a los ejemplos anteriores para evitar que los objetos singleton se regeneren cuando se deserializan :

private Object readResolve() throws ObjectStreamException{
    return mInstance;
}

Es decir, el objeto mInstance se devuelve en el método readResolve (), en lugar de generar un nuevo objeto por defecto.

Supongo que te gusta

Origin blog.csdn.net/CHITTY1993/article/details/52234747
Recomendado
Clasificación