Factory-Konstruktoren
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 14 von 110.
Ein factory constructor ist ein spezieller constructor, der nicht immer eine neue instance erstellt. Im Gegensatz zu regulären constructor kann ein factory constructor eine vorhandene instance, einen Untertyp oder sogar null zurückgeben (wenn nullable). Du deklarierst ihn mit dem factory-Schlüsselwort.
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. Unabhängig davon, wie oft du Logger() aufrufst, erhältst du dasselbe Objekt. Dieses Muster wird häufig zur Implementierung von Singletons verwendet.
Factory-Konstruktoren unterscheiden sich in einem wichtigen Punkt von regulären Konstruktoren: Sie haben keinen Zugriff auf this, weil sie möglicherweise überhaupt 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 du die Kontrolle über die Erstellung von Instanzen benötigst, etwa um zwischengespeicherte Objekte zurückzugeben, Objekt-Pools zu implementieren oder anhand von Eingabeparametern zu entscheiden, welchen Untertyp du instanziierst.
Aufgabe
EinfachErstellen wir ein Benachrichtigungssystem, das Factory-Konstruktoren verwendet, um verschiedene Arten von Benachrichtigungen anhand einer einfachen String-Eingabe zu erstellen.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
notification.dart: Definiere eineNotification-Klasse, die als Grundlage für alle Benachrichtigungstypen dient. Deine Klasse sollte Folgendes enthalten:- Ein
String message-Feld - Einen privaten benannten Konstruktor
Notification._internal, der die Nachricht initialisiert - Einen Factory-Konstruktor
Notification(String type, String message), der abhängig vom Parametertypeverschiedene Benachrichtigungsuntertypen zurückgibt:- Wenn type
'email'ist, gib eineEmailNotificationzurück - Wenn type
'sms'ist, gib eineSMSNotificationzurück - Andernfalls gib eine
PushNotificationzurück
- Wenn type
- Eine
send()-Methode, dieSending: [message]ausgibt
- Ein
Erstelle in derselben Datei drei Unterklassen, die Notification erweitern:
EmailNotification: Überschreibesend(), sodassEmail: [message]ausgegeben wirdSMSNotification: Überschreibesend(), sodassSMS: [message]ausgegeben wirdPushNotification: Überschreibesend(), sodassPush: [message]ausgegeben wird
Jede Unterklasse benötigt einen Konstruktor, der eine message entgegennimmt und sie mit super._internal(message) an die übergeordnete Klasse übergibt.
main.dart: Importiere deine Benachrichtigungsklasse und erstelle mithilfe des Factory-Konstruktors drei Benachrichtigungen:- 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()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: Create an SMS notification with message 'Your code is 1234'
// TODO: Create a push notification with message '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 Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler