Das Singleton-Muster stellt sicher, dass immer nur eine Instanz einer Klasse erstellt wird. Wie baue ich das in Dart?
Antworten
Zu viele Anzeigen?Dank des Dart's Fabrikkonstrukteure ist es einfach, ein Singleton zu erstellen:
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
Sie können ihn wie folgt konstruieren
main() {
var s1 = Singleton();
var s2 = Singleton();
print(identical(s1, s2)); // true
print(s1 == s2); // true
}
Hier ist ein Vergleich verschiedener Möglichkeiten, ein Singleton in Dart zu erstellen.
1. Fabrik-Konstruktor
class SingletonOne {
SingletonOne._privateConstructor();
static final SingletonOne _instance = SingletonOne._privateConstructor();
factory SingletonOne() {
return _instance;
}
}
2. Statisches Feld mit Getter
class SingletonTwo {
SingletonTwo._privateConstructor();
static final SingletonTwo _instance = SingletonTwo._privateConstructor();
static SingletonTwo get instance => _instance;
}
3. Statisches Feld
class SingletonThree {
SingletonThree._privateConstructor();
static final SingletonThree instance = SingletonThree._privateConstructor();
}
Wie man instanziiert
Die oben genannten Singletons werden wie folgt instanziiert:
SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;
Anmerkung:
Ich habe diese Frage ursprünglich als Frage Aber ich habe festgestellt, dass alle oben genannten Methoden ihre Berechtigung haben und die Wahl weitgehend von den persönlichen Vorlieben abhängt.
Hier ist eine einfache Antwort:
- Die Klasse sollte eine
private
ystatic
Eigenschaft seines Typs. - Der Konstruktor sollte sein
private
um die Initialisierung externer Objekte zu verhindern. - Prüfen Sie, ob die Instanz
null
, wenn ja eine Instanz erzeugen und zurückgeben es, andernfalls wird die bestehende Instanz .
Implementierung (Werkvertragsnehmer)
class Singleton {
static Singleton? _instance;
Singleton._();
factory Singleton() => _instance ??= Singleton._();
void someMethod() {
// ...
}
}
Verwendung
Singleton().someMethod();
// prints "Same Singleton instance? true"
print('Same Singleton instance? ${Singleton().hashCode == Singleton().hashCode}');
Implementierung (Lazy Loading)
class Singleton {
static Singleton? _instance;
Singleton._();
static Singleton get instance => _instance ??= Singleton._();
void someMethod() {
...
}
...
}
Implementierung (Eager Loading)
class Singleton {
static Singleton _instance = Singleton._();
Singleton._();
static Singleton get instance => _instance;
void someMethod() {
...
}
...
}
Verwendung
Singleton.instance.someMethod();
Ich finde es nicht sehr intuitiv zu lesen new Singleton()
. Sie müssen die Dokumente lesen, um das zu wissen new
keine neue Instanz erzeugt, wie es normalerweise der Fall wäre.
Hier ist eine weitere Möglichkeit, Singletons zu erstellen (im Grunde das, was Andrew oben sagte).
lib/thing.dart
library thing;
final Thing thing = new Thing._private();
class Thing {
Thing._private() { print('#2'); }
foo() {
print('#3');
}
}
main.dart
import 'package:thing/thing.dart';
main() {
print('#1');
thing.foo();
}
Beachten Sie, dass das Singleton nicht erstellt wird, bevor der Getter das erste Mal aufgerufen wird, da Dart eine träge Initialisierung vornimmt.
Wenn Sie es vorziehen, können Sie Singletons auch als statische Getter auf die Singleton-Klasse implementieren, d.h. Thing.singleton
anstelle eines Top-Level-Getters.
Lesen Sie auch Bob Nystroms Meinung zu Singletons aus seinem Buch Game programming patterns .
Wie wäre es, wenn Sie einfach eine globale Variable in Ihrer Bibliothek verwenden, etwa so?
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);
}
Oder ist das verpönt?
Das Singleton-Muster ist in Java notwendig, wo das Konzept der Globals nicht existiert, aber es scheint, dass man in Dart nicht den langen Weg gehen muss.
- See previous answers
- Weitere Antworten anzeigen