Das Singleton-Muster stellt sicher, dass immer nur eine Instanz einer Klasse erstellt wird. Wie baue ich das in Dart?
Antworten
Zu viele Anzeigen?So implementiere ich Singleton in meinen Projekten
Inspiriert von Flutter Firebase => FirebaseFirestore.instance.collection('collectionName')
class FooAPI {
foo() {
// some async func to api
}
}
class SingletonService {
FooAPI _fooAPI;
static final SingletonService _instance = SingletonService._internal();
static SingletonService instance = SingletonService();
factory SingletonService() {
return _instance;
}
SingletonService._internal() {
// TODO: add init logic if needed
// FOR EXAMPLE API parameters
}
void foo() async {
await _fooAPI.foo();
}
}
void main(){
SingletonService.instance.foo();
}
Beispiel aus meinem Projekt
class FirebaseLessonRepository implements LessonRepository {
FirebaseLessonRepository._internal();
static final _instance = FirebaseLessonRepository._internal();
static final instance = FirebaseLessonRepository();
factory FirebaseLessonRepository() => _instance;
var lessonsCollection = fb.firestore().collection('lessons');
// ... other code for crud etc ...
}
// then in my widgets
FirebaseLessonRepository.instance.someMethod(someParams);
Hier ist ein kurzes Beispiel, das die anderen Lösungen kombiniert. Der Zugriff auf das Singleton kann durch erfolgen:
- Mit einer
singleton
globale Variable, die auf die Instanz zeigt. - Die gemeinsame
Singleton.instance
Muster. - Verwendung des Standardkonstruktors, der eine Fabrik ist, die die Instanz zurückgibt.
Anmerkung: Sie sollten nur eine der drei Optionen implementieren, damit der Code, der das Singleton verwendet, konsistent ist.
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;
}
Wenn Sie eine komplexe Initialisierung durchführen müssen, müssen Sie dies einfach tun, bevor Sie die Instanz später im Programm verwenden.
Beispiel
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
}
Seit Dart 2.13
Version, ist es sehr einfach mit late
Stichwort. Late
ermöglicht es uns, Objekte nachlässig zu instanziieren.
Sie können es als Beispiel sehen:
class LazySingletonExample {
LazySingletonExample._() {
print('instance created.');
}
static late final LazySingletonExample instance = LazySingletonExample._();
}
Hinweis: Beachten Sie, dass es nur einmal instanziiert wird, wenn Sie lazy
instance
Feld.
Geänderte Antwort von @Seth Ladd auf die Frage, wer den Swift-Stil von Singleton bevorzugt, wie .shared
:
class Auth {
// singleton
static final Auth _singleton = Auth._internal();
factory Auth() => _singleton;
Auth._internal();
static Auth get shared => _singleton;
// variables
String username;
String password;
}
Beispiel:
Auth.shared.username = 'abc';
Wenn Sie Flutter verwenden und provider
Paket für die Zustandsverwaltung ist das Erstellen und Verwenden eines Singletons recht einfach.
- Eine Instanz erstellen
void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => SomeModel()), Provider(create: (context) => SomeClassToBeUsedAsSingleton()), ], child: MyApp(), ), ); }
- Holen Sie die Instanz
Widget build(BuildContext context) { var instance = Provider.of<SomeClassToBeUsedAsSingleton>(context); ...