Menu
Coddy logo textTech

Konstruktory fabryczne

Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 14 z 110.

Konstruktor fabrykujący to specjalny konstruktor, który nie zawsze tworzy nową instancję. W przeciwieństwie do zwykłych konstruktorów konstruktor fabrykujący może zwrócić istniejącą instancję, podtyp albo nawet null (jeśli jest dopuszczalny). Deklarujesz go za pomocą słowa kluczowego factory.

class Logger {
  static final Logger _instance = Logger._internal();
  
  // Prywatny konstruktor nazwany
  Logger._internal();
  
  // Konstruktor fabryczny
  factory Logger() {
    return _instance;
  }
}

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

W tym przykładzie konstruktor fabryczny zawsze zwraca tę samą instancję. Niezależnie od tego, ile razy wywołasz Logger(), otrzymasz identyczny obiekt. Ten wzorzec jest powszechnie stosowany do implementowania singletonów.

Konstruktory fabryczne różnią się od zwykłych konstruktorów w istotny sposób: nie mają dostępu do this, ponieważ mogą w ogóle nie tworzyć nowej instancji. Zamiast tego muszą jawnie zwrócić obiekt:

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._(); }

Konstruktory fabryczne są przydatne, gdy potrzebujesz kontrolować tworzenie instancji, na przykład zwracać obiekty z pamięci podręcznej, implementować pule obiektów lub decydować, który podtyp utworzyć na podstawie parametrów wejściowych.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system powiadomień, który używa konstruktorów fabrycznych do tworzenia różnych typów powiadomień na podstawie prostego wejściowego ciągu znaków.

Utworzysz dwa pliki, aby uporządkować swój kod:

  • notification.dart: Zdefiniuj klasę Notification, która będzie klasą bazową dla wszystkich typów powiadomień. Twoja klasa powinna zawierać:
    • Pole String message
    • Prywatny konstruktor nazwany Notification._internal, który inicjalizuje wiadomość
    • Konstruktor fabryczny Notification(String type, String message), który zwraca różne podtypy powiadomień w zależności od parametru type:
      • Jeśli type ma wartość 'email', zwróć EmailNotification
      • Jeśli type ma wartość 'sms', zwróć SMSNotification
      • W przeciwnym razie zwróć PushNotification
    • Metodę send(), która wyświetla Sending: [message]

W tym samym pliku utwórz trzy podklasy rozszerzające Notification:

  • EmailNotification: Zastąp metodę send(), aby wyświetlała Email: [message]
  • SMSNotification: Zastąp metodę send(), aby wyświetlała SMS: [message]
  • PushNotification: Zastąp metodę send(), aby wyświetlała Push: [message]

Każda podklasa potrzebuje konstruktora, który przyjmuje message i przekazuje go do klasy nadrzędnej za pomocą super._internal(message).

  • main.dart: Zaimportuj klasę powiadomień i utwórz trzy powiadomienia za pomocą konstruktora fabrycznego:
    • Powiadomienie e-mail z wiadomością 'Welcome!'
    • Powiadomienie SMS z wiadomością 'Your code is 1234'
    • Powiadomienie push z wiadomością 'New update available'
    Wywołaj send() dla każdego powiadomienia w podanej wyżej kolejności.

Oczekiwany wynik:

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

Spróbuj swoich sił

import 'notification.dart';

void main() {
  // TODO: Utwórz powiadomienie e-mail z wiadomością 'Welcome!'
  
  // TODO: Utwórz powiadomienie SMS z wiadomością 'Your code is 1234'
  
  // TODO: Utwórz powiadomienie push z wiadomością 'New update available'
  
  // TODO: Wywołaj send() kolejno dla każdego powiadomienia
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Dart online