ejercicios - ¿Cómo construyes un Singleton en Dart?
ejercicios singleton java (6)
¿Qué tal si usamos una variable global dentro de tu biblioteca, como tal?
single.dart
:
library singleton;
var Singleton = new Impl();
class Impl {
int i;
}
main.dart
:
import ''single.dart'';
void main() {
var a = Singleton;
var b = Singleton;
a.i = 2;
print(b.i);
}
¿O está mal visto?
El patrón de singleton es necesario en Java, donde el concepto de globales no existe, pero parece que no se necesita recorrer un largo camino en Dart.
El patrón singleton asegura que solo se crea una instancia de una clase. ¿Cómo construyo esto en Dart?
Aquí hay otra manera posible:
void main() {
var s1 = Singleton.instance;
s1.somedata = 123;
var s2 = Singleton.instance;
print(s2.somedata); // 123
print(identical(s1, s2)); // true
print(s1 == s2); // true
//var s3 = new Singleton(); //produces a warning re missing default constructor and breaks on execution
}
class Singleton {
static final Singleton _singleton = new Singleton._internal();
Singleton._internal();
static Singleton get instance => _singleton;
var somedata;
}
Aquí hay un ejemplo conciso que combina las otras soluciones. El acceso al singleton se puede hacer de la siguiente manera:
- Usando una variable global
singleton
que apunta a la instancia. - El patrón común
Singleton.instance
. - Usar el constructor predeterminado, que es una fábrica que devuelve la instancia.
Nota: debe implementar solo una de las tres opciones para que el código que utiliza el singleton sea coherente.
Singleton get singleton => Singleton.instance;
ComplexSingleton get complexSingleton => ComplexSingleton._instance;
class Singleton {
static final Singleton instance = Singleton._private();
Singleton._private();
factory Singleton() => instance;
}
class ComplexSingleton {
static ComplexSingleton _instance;
static ComplexSingleton get instance => _instance;
static void init(arg) => _instance ??= ComplexSingleton._init(arg);
final property;
ComplexSingleton._init(this.property);
factory ComplexSingleton() => _instance;
}
Si necesita realizar una inicialización compleja, tendrá que hacerlo antes de usar la instancia más adelante en el programa.
Ejemplo
void main() {
print(identical(singleton, Singleton.instance)); // true
print(identical(singleton, Singleton())); // true
print(complexSingleton == null); // true
ComplexSingleton.init(0);
print(complexSingleton == null); // false
print(identical(complexSingleton, ComplexSingleton())); // true
}
Dart singleton por const constructor y fábrica
class Singleton {
factory Singleton() =>
const Singleton._internal_();
const Singleton._internal_();
}
void main() {
print(new Singleton() == new Singleton());
print(identical(new Singleton() , new Singleton()));
}
Gracias a los constructores de fábrica de Dart, es fácil construir un singleton:
class Singleton {
static final Singleton _singleton = new Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
Puedes construirlo con new
main() {
var s1 = new Singleton();
var s2 = new Singleton();
print(identical(s1, s2)); // true
print(s1 == s2); // true
}
No me resulta muy intuitivo leer el nuevo Singleton (). Tienes que leer los documentos para saber que lo nuevo no está creando una nueva instancia, como lo haría normalmente.
Aquí hay otra forma de hacer singletons (Básicamente, lo que dijo Andrew anteriormente).
lib / thing.dart
library thing;
final Thing thing = new Thing._private();
class Thing {
Thing._private() { print(''#2''); }
foo() {
print(''#3'');
}
}
principal.dart
import ''package:thing/thing.dart'';
main() {
print(''#1'');
thing.foo();
}
Tenga en cuenta que el singleton no se crea hasta la primera vez que se llama al getter debido a la inicialización perezosa de Dart.
Si lo prefiere, también puede implementar singletons como getter estático en la clase singleton. es decir, Thing.singleton, en lugar de un getter de nivel superior.
Lea también la versión de Bob Nystrom de singletons de su libro de patrones de programación de juegos .