504 Stimmen

Wie baut man ein Singleton in Dart?

Das Singleton-Muster stellt sicher, dass immer nur eine Instanz einer Klasse erstellt wird. Wie baue ich das in Dart?

759voto

Seth Ladd Punkte 93613

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
}

577voto

Suragch Punkte 420096

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.

87voto

Hamed Punkte 5282

Hier ist eine einfache Antwort:

  • Die Klasse sollte eine private y static 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();

51voto

Greg Lowe Punkte 13532

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 .

30voto

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X