Menu
Coddy logo textTech

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)); // true

In 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.

challenge icon

Aufgabe

Einfach

Lassen 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 eine Notification-Klasse, die als Basis für alle Benachrichtigungstypen dient. Ihre Klasse sollte Folgendes haben:
    • Ein String message Feld
    • Einen privaten benannten Konstruktor Notification._internal, der die Nachricht initialisiert
    • Einen Factory-Konstruktor Notification(String type, String message), der basierend auf dem Parameter type verschiedene Benachrichtigungs-Subtypen zurückgibt:
      • Wenn der Typ 'email' ist, geben Sie eine EmailNotification zurück
      • Wenn der Typ 'sms' ist, geben Sie eine SMSNotification zurück
      • Andernfalls geben Sie eine PushNotification zurück
    • Eine send() Methode, die Sending: [message] ausgibt

Erstellen Sie in derselben Datei drei Unterklassen, die Notification erweitern:

  • EmailNotification: Überschreiben Sie send(), um Email: [message] auszugeben
  • SMSNotification: Überschreiben Sie send(), um SMS: [message] auszugeben
  • PushNotification: Überschreiben Sie send(), um Push: [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'
    Rufen Sie send() für jede Benachrichtigung in der oben aufgeführten Reihenfolge auf.

Erwartete Ausgabe:

Email: Welcome!
SMS: Your code is 1234
Push: New update available

Spickzettel

Ein Factory-Konstruktor ist ein spezieller Konstruktor, der mit dem Schlüsselwort factory deklariert wird und nicht immer eine neue Instanz erstellt. Im Gegensatz zu regulären Konstruktoren kann er eine bestehende Instanz, einen Subtyp oder null zurückgeben.

Factory-Konstruktoren haben keinen Zugriff auf this und müssen explizit ein Objekt zurückgeben.

Beispiel für das Singleton-Muster:

class Logger {
  static final Logger _instance = Logger._internal();
  
  Logger._internal(); // Privater benannter Konstruktor
  
  factory Logger() {
    return _instance; // Gibt immer dieselbe Instanz zurück
  }
}

Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // true

Rückgabe verschiedener Subtypen:

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, um die Instanzerstellung zu steuern, z. B. um gecachte Objekte zurückzugeben, Objekt-Pools zu implementieren oder basierend auf Eingabeparametern zu entscheiden, welcher Subtyp instanziiert werden soll.

Probier 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
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung