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)); // trueW 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.
Wyzwanie
ŁatwyStwó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 parametrutype:- Jeśli type ma wartość
'email', zwróćEmailNotification - Jeśli type ma wartość
'sms', zwróćSMSNotification - W przeciwnym razie zwróć
PushNotification
- Jeśli type ma wartość
- Metodę
send(), która wyświetlaSending: [message]
- Pole
W tym samym pliku utwórz trzy podklasy rozszerzające Notification:
EmailNotification: Zastąp metodęsend(), aby wyświetlałaEmail: [message]SMSNotification: Zastąp metodęsend(), aby wyświetlałaSMS: [message]PushNotification: Zastąp metodęsend(), aby wyświetlałaPush: [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'
send()dla każdego powiadomienia w podanej wyżej kolejności.- Powiadomienie e-mail z wiadomością
Oczekiwany wynik:
Email: Welcome!
SMS: Your code is 1234
Push: New update availableSpró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
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP
Pliki zewnętrzneBiblioteki i importyWprowadzenie do OOPKlasy a obiektySłowo kluczowe thisMetodyZmienne instancjiPodstawy konstruktorówPowtórka – prosty kalkulator4Bezpieczeństwo wartości null
Wprowadzenie do bezpieczeństwa wartości nullTypy dopuszczające null i niedopuszczające nullOperatory ? i !Słowo kluczowe late a bezpieczeństwo wartości nullOperatory uwzględniające nullBezpieczeństwo wartości null w klasachPodsumowanie — system profili użytkowników7Klasy abstrakcyjne i interfejsy
Klasy abstrakcyjneMetody abstrakcyjneInterfejsy w DartInterfejsy niejawneImplementowanie a rozszerzanieWiele interfejsówPowtórka — kalkulator kształtów10Kolekcje i typy generyczne
Przegląd List, Set i MapKolekcje bezpieczne typowoKlasy generyczneMetody generyczneOgraniczenia typów generycznychIterable i IteratorPowtórka — generyczne przechowywanie danych13Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieMetody rozszerzająceKlasy wywoływalneKlasy zapieczętowane (Dart 3)Rekordy (Dart 3)Wzorce i dopasowywanie (3.0)Typy wyliczeniowe z metodami16Projekt: Zarządzanie biblioteką
Omówienie projektuKlasy książek i użytkowników2Konstruktory w Dart
Konstruktor domyślnyKonstruktory nazwaneListy inicjalizująceKonstruktory stałeKonstruktory fabryczneKonstruktory przekierowującePodsumowanie — budowanie kształtów5Hermetyzacja
Elementy publiczne a prywatneKonwencja prefiksu _Prywatność na poziomie bibliotekiGettery i settery — szczegółowoUkrywanie informacjiPodsumowanie — dane uczniów8Domieszki
Wprowadzenie do domieszekTworzenie domieszekKorzystanie z wielu domieszekSłowo kluczowe on w domieszkachDomieszka a dziedziczenieDomieszka a interfejsPodsumowanie – system zwierząt11Metody specjalne
Nadpisanie toString()Nadpisanie hashCode i ==Interfejs ComparableMetoda call()Nadpisanie noSuchMethodPodsumowanie — własna kolekcja14Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy3Właściwości klas
Elementy instancji a elementy statycznePola final i constZmienne inicjalizowane z opóźnieniemMetody i pola statyczneGettery i setteryPowtórzenie – menedżer kont bankowych6Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superPrzesłanianie metodAdnotacja @overrideSłowo kluczowe final dla klasKonstruktory i dziedziczeniePowtórzenie – hierarchia pracowników9Polimorfizm
Podstawy polimorfizmuPolimorfizm za pomocą interfejsówSprawdzanie typu w czasie działaniaOperatory is i asSłowo kluczowe covariantPodsumowanie — procesor płatnościPoćwicz samodzielnie: Kompilator Dart online