Singleton en Flutter

- Andrés Cruz

In english
Singleton en Flutter

De manera simple, singleton asegura que una clase tenga solo una instancia en todas las aplicaciones y proporciona un punto de acceso global.

Una instancia u objeto de una Clase es una representación concreta y específica de una Clase

El patrón Singleton es un patrón de diseño de los muchos que existen que garantiza que una clase tenga una sola instancia; y es básicamente eso; para ello, se emplea la programación orientada a objetos. En Flutter, el patrón Singleton se utiliza a menudo en combinación con el diseño Material para proporcionar un acceso global a determinados widgets de Material que se utilizan en la aplicación.

Por ejemplo, un singleton DatabaseHelper puede utilizarse para proporcionar acceso global a una base de datos SQLite; esta es una implementación que comunnente hago en el curso de Flutter y en mis aplicaciones; este tipo de adaptaciones, son comunes en Flutter y facilitan el proceso de creación de aplicaciones organizadas, modulares y escalabes.

En general, la implementación de un patrón Singleton en Flutter sigue los mismos principios que en cualquier otro lenguaje de programación, garantizando que solo se cree una instancia de una determinada clase, y proporcionando un punto de acceso global para esa instancia.

¿Cuándo usarlo?

Este patrón se usa cuando necesitamos solo una instancia de algo en nuestra aplicación. Por ejemplo, en el caso de un inicio de sesión de usuario en nuestra aplicación, necesitamos esta información en varias partes, pero sería demasiado costoso en términos de procesamiento tener la información de usuario para cada flujo. En este caso podemos crear un singleton de usuario y sería la misma instancia para todos los flujos.

Beneficios

  • Acceso controlado a una única instancia de datos. Es decir, puedes tener un control estricto sobre cómo y cuándo acceden los clientes.
  • La instancia se crea solo cuando se va a utilizar.
  • Accesible desde cualquier parte, singleton es una mejora sobre las variables globales.

¿Cómo garantizamos que una Clase tiene solo una instancia?

Una solución es hacer que la misma Clase sea responsable de su única instancia. La Clase puede garantizar que no se pueda crear ninguna otra instancia y debe proporcionar una forma de acceder a la instancia.

Singleton en Flutter

Una forma de crear un singleton en Dart es usar constructores factory. Como ejemplo, vamos a crear un singleton de usuario que tendrá el nombre de usuario. Para ello, primero creamos una Clase normal llamada UserSingleton. Lo hacemos un singleton creando una variable privada _instancia de tipo UserSingleton. Luego creamos mediante un factory UserSingleton() que devuelve la instancia.

Finalmente, creamos el constructor UserSingleton._internal() el cual es llamado exactamente una vez, y como es privado solo puede ser llamado en esta Clase y también evitamos que sea instanciado fuera de aquí. Este constructor se puede utilizar para inicializar la lógica.

En el ejemplo que vamos a usar, también tenemos un método para actualizar el nombre de usuario.

Finalmente, el UserSingleton es el siguiente:

class UserSingleton {
  static final UserSingleton _instance = UserSingleton._internal();
  String userName = 'Alvaro';
  // using a factory is important
  // because it promises to return _an_ object of this type
  // but it doesn't promise to make a new one.
  factory UserSingleton() {
    return _instance;
  }
  // This named constructor is the "real" constructor
  // It'll be called exactly once, by the static property assignment         above
  // it's also private, so it can only be called in this class
  UserSingleton._internal() {
    // initialization logic
  }
  // rest of class as normal, for example:
  void updateUserName(String name) {
    userName = name;
  }
}

Aquí puedes ver otra implementación del Singleton para un helper de una base de datos:

class DatabaseHelper {
 static DatabaseHelper _instance;
 factory DatabaseHelper() => _instance ??= DatabaseHelper._();
 DatabaseHelper._();
 // aquí puedes agregar métodos y propiedades relacionados con la base de datos
}

En este ejemplo, la clase DatabaseHelper tiene una propiedad de clase estática _instance que contiene la única instancia de la clase. Un constructor factory es utilizado para crear una nueva instancia de la clase si aún no existe, o para devolver la instancia existente si ya ha sido creada. 

Recuerda que…

La utilización de constructores factory en Dart se utiliza para cuando no es necesario crear una instancia de la clase en sí misma o en las que se tiene una instancia de una subclase o de la misma clase

Al utilizar el constructor factory, se puede controlar cómo se crea la instancia de la clase y, a menudo, se puede optimizar y reutilizar la misma instancia para llamadas posteriores. Esto puede ser útil en situaciones donde crear una nueva instancia de una clase puede ser costoso en términos de tiempo y recursos.

El constructor actual DatabaseHelper._() es privado, lo que significa que no puede ser llamado desde fuera de la clase, forzando la creación de una instancia a través del constructor de fábrica/factory.

Para utilizar DatabaseHelper en tu aplicación, simplemente llama al constructor de fábrica, como se muestra a continuación:

DatabaseHelper db = DatabaseHelper();

De esta manera, solo se puede crear una instancia de la clase DatabaseHelper, y se puede acceder a ella en cualquier parte de la aplicación.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.