Factory-Konstruktoren
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 14 von 110.
Ein Factory-Konstruktor ist ein spezieller Konstruktor, der nicht immer eine neue Instanz erstellt. Im Gegensatz zu regulären Konstruktoren kann ein Factory-Konstruktor eine bestehende Instanz, einen Subtyp oder sogar null (falls nullbar) zurückgeben. Sie deklarieren ihn mit dem Schlüsselwort factory.
class Logger {
static final Logger _instance = Logger._internal();
// Privater benannter Konstruktor
Logger._internal();
// Factory-Konstruktor
factory Logger() {
return _instance;
}
}
Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // trueIn diesem Beispiel gibt der Factory-Konstruktor immer dieselbe Instanz zurück. Egal wie oft Sie Logger() aufrufen, Sie erhalten das identische Objekt. Dieses Muster wird häufig zur Implementierung von Singletons verwendet.
Factory-Konstruktoren unterscheiden sich von regulären Konstruktoren in einem wesentlichen Punkt: Sie haben keinen Zugriff auf this, da sie möglicherweise gar keine neue Instanz erstellen. Stattdessen müssen sie explizit ein Objekt zurückgeben:
class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle();
if (type == 'square') return Square();
return Rectangle();
}
}
class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }Factory-Konstruktoren sind nützlich, wenn Sie die Kontrolle über die Instanzerstellung benötigen, z. B. um zwischengespeicherte Objekte zurückzugeben, Objekt-Pools zu implementieren oder zu entscheiden, welcher Subtyp basierend auf den Eingabeparametern instanziiert werden soll.
Aufgabe
EinfachLassen Sie uns ein Benachrichtigungssystem erstellen, das Factory-Konstruktoren verwendet, um verschiedene Arten von Benachrichtigungen basierend auf einer einfachen String-Eingabe zu erstellen.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
notification.dart: Definieren Sie eineNotification-Klasse, die als Basis für alle Benachrichtigungstypen dient. Ihre Klasse sollte Folgendes haben:- Ein
String messageFeld - Einen privaten benannten Konstruktor
Notification._internal, der die Nachricht initialisiert - Einen Factory-Konstruktor
Notification(String type, String message), der basierend auf dem Parametertypeverschiedene Benachrichtigungs-Subtypen zurückgibt:- Wenn der Typ
'email'ist, geben Sie eineEmailNotificationzurück - Wenn der Typ
'sms'ist, geben Sie eineSMSNotificationzurück - Andernfalls geben Sie eine
PushNotificationzurück
- Wenn der Typ
- Eine
send()Methode, dieSending: [message]ausgibt
- Ein
Erstellen Sie in derselben Datei drei Unterklassen, die Notification erweitern:
EmailNotification: Überschreiben Siesend(), umEmail: [message]auszugebenSMSNotification: Überschreiben Siesend(), umSMS: [message]auszugebenPushNotification: Überschreiben Siesend(), umPush: [message]auszugeben
Jede Unterklasse benötigt einen Konstruktor, der eine message entgegennimmt und diese mit super._internal(message) an die Elternklasse übergibt.
main.dart: Importieren Sie Ihre Benachrichtigungsklasse und erstellen Sie drei Benachrichtigungen mit dem Factory-Konstruktor:- Eine E-Mail-Benachrichtigung mit der Nachricht
'Welcome!' - Eine SMS-Benachrichtigung mit der Nachricht
'Your code is 1234' - Eine Push-Benachrichtigung mit der Nachricht
'New update available'
send()für jede Benachrichtigung in der oben aufgeführten Reihenfolge auf.- Eine E-Mail-Benachrichtigung mit der Nachricht
Erwartete Ausgabe:
Email: Welcome!
SMS: Your code is 1234
Push: New update availableProbier es selbst
import 'notification.dart';
void main() {
// TODO: Erstelle eine E-Mail-Benachrichtigung mit der Nachricht 'Welcome!'
// TODO: Erstelle eine SMS-Benachrichtigung mit der Nachricht 'Your code is 1234'
// TODO: Erstelle eine Push-Benachrichtigung mit der Nachricht 'New update available'
// TODO: Rufe send() für jede Benachrichtigung der Reihe nach auf
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenInstanzvariablenKonstruktor-GrundlagenWiederholung – Einfacher Taschenrechner4Null-Sicherheit
Einführung in Null-SicherheitNullable vs. Non-NullableDie ? und ! OperatorenLate-Schlüsselwort & Null-SicherheitNull-aware OperatorenNull-Sicherheit in KlassenZusammenfassung – Benutzerprofil-System7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrfache InterfacesRückblick – Shape Calculator10Collections & Generics
Überblick über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische ConstraintsIterable & IteratorZusammenfassung – Generische Speicherung13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
Standard-KonstruktorBenannte KonstruktorenInitialisierungslistenKonstante KonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenZusammenfassung – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _ Präfix-KonventionSichtbarkeit auf Library-EbeneGetter & Setter im DetailInformation HidingRückblick – Schülerdatensätze8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas on-Schlüsselwort in MixinsMixin vs. VererbungMixin vs. InterfaceZusammenfassung - Tiersystem11Spezielle Methoden
toString() überschreibenhashCode & == überschreibenComparable-Interfacecall()-MethodenoSuchMethod überschreibenZusammenfassung – Eigene Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster3Klasseneigenschaften
Instanz- vs. statische MemberFinal & Const FelderLate-VariablenStatische Methoden & FelderGetter und SetterZusammenfassung – Bankkonto-Manager6Vererbung
Grundlagen der VererbungDas super-SchlüsselwortMethoden überschreibenDie @override-AnnotationDas final-Klassen-SchlüsselwortKonstruktoren & VererbungRückblick – Mitarbeiter-Hierarchie9Polymorphismus
Polymorphismus-GrundlagenPolymorphismus über InterfacesTypprüfung zur LaufzeitDie is & as OperatorenDas covariant SchlüsselwortZusammenfassung – Payment Processor