¿Cómo se construye un Singleton en Dart?
El patrón singleton garantiza que solo se cree una instancia de una clase. ¿Cómo construyo esto en Dart?
Gracias a los constructores de fábrica de Dart , es fácil construir un singleton:
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
Puedes construirlo así.
main() {
var s1 = Singleton();
var s2 = Singleton();
print(identical(s1, s2)); // true
print(s1 == s2); // true
}
A continuación se muestra una comparación de varias formas diferentes de crear un singleton en Dart.
1. Constructor de fábrica
class SingletonOne {
SingletonOne._privateConstructor();
static final SingletonOne _instance = SingletonOne._privateConstructor();
factory SingletonOne() {
return _instance;
}
}
2. Campo estático con getter
class SingletonTwo {
SingletonTwo._privateConstructor();
static final SingletonTwo _instance = SingletonTwo._privateConstructor();
static SingletonTwo get instance => _instance;
}
3. Campo estático
class SingletonThree {
SingletonThree._privateConstructor();
static final SingletonThree instance = SingletonThree._privateConstructor();
}
Cómo crear una instancia
Los singletons anteriores se crean instancias de esta manera:
SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;
Nota:
Originalmente hice esto como una pregunta , pero descubrí que todos los métodos anteriores son válidos y la elección depende en gran medida de las preferencias personales.
Aquí hay una respuesta simple:
- La clase debe tener una propiedad
private
ystatic
de su tipo. - El constructor debe
private
evitar la inicialización de objetos externos. - Compruebe si la instancia es
null
, en caso afirmativo, cree una instancia y devuélvala ; de lo contrario, devuelva la instancia existente .
Implementación (contratista de fábrica)
class Singleton {
static Singleton? _instance;
Singleton._();
factory Singleton() => _instance ??= Singleton._();
void someMethod() {
// ...
}
}
Uso
Singleton().someMethod();
// prints "Same Singleton instance? true"
print('Same Singleton instance? ${Singleton().hashCode == Singleton().hashCode}');
Implementación (carga diferida)
class Singleton {
static Singleton? _instance;
Singleton._();
static Singleton get instance => _instance ??= Singleton._();
void someMethod() {
...
}
...
}
Implementación (carga ansiosa)
class Singleton {
static Singleton _instance = Singleton._();
Singleton._();
static Singleton get instance => _instance;
void someMethod() {
...
}
...
}
Uso
Singleton.instance.someMethod();
No me parece una lectura muy intuitiva new Singleton()
. Debe leer los documentos para saber que new
en realidad no se está creando una nueva instancia, como lo haría normalmente.
Aquí hay otra forma de hacer singletons (básicamente lo que Andrew dijo anteriormente).
lib/cosa.dart
library thing;
final Thing thing = new Thing._private();
class Thing {
Thing._private() { print('#2'); }
foo() {
print('#3');
}
}
dardo.principal
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 captador debido a la inicialización diferida de Dart.
Si lo prefiere, también puede implementar singletons como captadores estáticos en la clase singleton. es decir Thing.singleton
, en lugar de un captador de nivel superior.
Lea también la versión de Bob Nystrom sobre los singletons de su libro de patrones de programación de juegos .