Patrón de diseño Singleton | Implementación

 

Patrón de diseño Singleton | Introducción
El patrón singleton es uno de los patrones de diseño más simples. A veces necesitamos tener solo una instancia de nuestra clase, por ejemplo, una sola conexión de base de datos compartida por varios objetos, ya que crear una conexión de base de datos separada para cada objeto puede ser costoso. De manera similar, puede haber un solo administrador de configuración o administrador de errores en una aplicación que maneje todos los problemas en lugar de crear varios administradores.
Definición:  
El patrón singleton es un patrón de diseño que restringe la instanciación de una clase a un objeto.  
Veamos varias opciones de diseño para implementar dicha clase. Si tiene un buen manejo de las variables de clase estáticas y los modificadores de acceso, esta no debería ser una tarea difícil.
 
Método 1: Implementación clásica 
 

Java

// Classical Java implementation of singleton
// design pattern
class Singleton
{
    private static Singleton obj;
 
    // private constructor to force use of
    // getInstance() to create Singleton object
    private Singleton() {}
 
    public static Singleton getInstance()
    {
        if (obj==null)
            obj = new Singleton();
        return obj;
    }
}
 

Aquí hemos declarado getInstance() static para que podamos llamarlo sin instanciar la clase. La primera vez que se llama a getInstance(), se crea un nuevo objeto único y, después, simplemente devuelve el mismo objeto. Tenga en cuenta que Singleton obj no se crea hasta que lo necesitemos y llamemos al método getInstance(). Esto se llama instanciación perezosa.
El principal problema con el método anterior es que no es seguro para subprocesos. Considere la siguiente secuencia de ejecución.
 

singleton

Esta secuencia de ejecución crea dos objetos para singleton. Por lo tanto, esta implementación clásica no es segura para subprocesos.
 
Método 2: sincronizar getInstance() 
 

Java

// Thread Synchronized Java implementation of
// singleton design pattern
class Singleton
{
    private static Singleton obj;
 
    private Singleton() {}
 
    // Only one thread can execute this at a time
    public static synchronized Singleton getInstance()
    {
        if (obj==null)
            obj = new Singleton();
        return obj;
    }
}

Aquí, el uso sincronizado garantiza que solo un subproceso a la vez pueda ejecutar getInstance(). 
La principal desventaja de este método es que usar sincronizado cada vez que se crea el objeto único es costoso y puede disminuir el rendimiento de su programa. Sin embargo, si el rendimiento de getInstance() no es crítico para su aplicación, este método proporciona una solución limpia y simple.
 
Método 3: instanciación ansiosa 
 

Java

// Static initializer based Java implementation of
// singleton design pattern
class Singleton
{
    private static Singleton obj = new Singleton();
 
    private Singleton() {}
 
    public static Singleton getInstance()
    {
        return obj;
    }
}

Aquí hemos creado una instancia de singleton en un inicializador estático. JVM ejecuta el inicializador estático cuando se carga la clase y, por lo tanto, se garantiza que esto es seguro para subprocesos. Use este método solo cuando su clase singleton sea liviana y se use durante la ejecución de su programa.
 
Método 4 (mejor): use » Bloqueo de doble verificación » 
Si observa cuidadosamente una vez que se crea un objeto, la sincronización ya no es útil porque ahora obj no será nulo y cualquier secuencia de operaciones conducirá a resultados consistentes. 
Por lo tanto, solo adquiriremos el bloqueo en getInstance() una vez, cuando el obj sea nulo. De esta forma solo sincronizamos el primer paso, justo lo que queremos. 
 

Java

// Double Checked Locking based Java implementation of
// singleton design pattern
class Singleton
{
    private static volatile Singleton obj  = null;
 
    private Singleton() {}
 
    public static Singleton getInstance()
    {
        if (obj == null)
        {
            // To make thread safe
            synchronized (Singleton.class)
            {
                // check again as multiple threads
                // can reach above step
                if (obj==null)
                    obj = new Singleton();
            }
        }
        return obj;
    }
}

Hemos declarado obj volátil , lo que garantiza que varios subprocesos ofrezcan la variable obj correctamente cuando se inicializa en la instancia de Singleton. Este método reduce drásticamente la sobrecarga de llamar al método sincronizado cada vez.
  
Referencias: 
Libro Head First Design Patterns (muy recomendado) 
https://en.wikipedia.org/wiki/Singleton_pattern
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *