Wzorzec Factory
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 91 z 110.
Wzorzec Fabryka deleguje tworzenie obiektów do osobnej metody lub klasy, pozwalając tworzyć obiekty bez określania ich dokładnej klasy. Różni się to od konstruktora fabrykującego, o którym uczyłeś się wcześniej — wzorzec Fabryka to podejście projektowe, w którym logika tworzenia jest scentralizowana i może zwracać różne typy w zależności od danych wejściowych.
Rozważ scenariusz, w którym musisz tworzyć różne typy powiadomień. Zamiast pozwalać klientowi decydować, którą klasę utworzyć, tę decyzję podejmuje fabryka:
abstract class Notification {
void send(String message);
}
class EmailNotification implements Notification {
@override
void send(String message) => print('Email: $message');
}
class SMSNotification implements Notification {
@override
void send(String message) => print('SMS: $message');
}
class NotificationFactory {
static Notification create(String type) {
switch (type) {
case 'email':
return EmailNotification();
case 'sms':
return SMSNotification();
default:
return EmailNotification();
}
}
}
void main() {
var notification = NotificationFactory.create('sms');
notification.send('Hello!'); // SMS: Hello!
}Kod klienta nie musi znać EmailNotification ani SMSNotification — po prostu prosi fabrykę o powiadomienie określonego typu. Dzięki temu łatwo dodawać nowe typy powiadomień: modyfikujesz tylko fabrykę, a nie każde miejsce, w którym tworzone są powiadomienia.
Użyj wzorca Factory, gdy tworzenie obiektów wymaga złożonej logiki, gdy chcesz ukryć klasy implementacyjne przed klientami lub gdy dokładny typ do utworzenia zależy od warunków w czasie wykonywania.
Wyzwanie
ŁatwyZbudujmy generator dokumentów z użyciem wzorca Fabryka! Utworzysz system, który za pośrednictwem scentralizowanej fabryki tworzy różne rodzaje dokumentów (raporty, faktury i listy), dzięki czemu kod klienta nie musi znać konkretnych klas dokumentów.
Podzielisz kod na dwa pliki:
document_factory.dart: Utwórz tutaj system dokumentów:- Klasa abstrakcyjna
Documentz metodągenerate(String content), która zwraca wartość typuString - Trzy konkretne klasy implementujące
Document:Report— jej metodageneratezwraca=== REPORT ===\n[content]\n=============Invoice— jej metodageneratezwracaINVOICE\n--------\n[content]\nTotal DueLetter— jej metodageneratezwracaDear Reader,\n[content]\nSincerely
- Klasa
DocumentFactoryze statyczną metodącreate(String type), która zwraca odpowiedni obiektDocumentna podstawie ciągu znaków określającego typ:"report","invoice"lub"letter". Dla dowolnego nieznanego typu zwróć obiektLetterjako wartość domyślną
- Klasa abstrakcyjna
main.dart: Zaimportuj fabrykę dokumentów i pokaż, jak fabryka tworzy różne rodzaje dokumentów, bez konieczności znajomości przez klienta konkretnych klas:- Użyj fabryki, aby utworzyć raport, a następnie wyświetl wynik jego wygenerowania z treścią
Sales increased by 25% - Wyświetl pusty wiersz
- Użyj fabryki, aby utworzyć fakturę, a następnie wyświetl wynik jej wygenerowania z treścią
Widget x3 - $150 - Wyświetl pusty wiersz
- Użyj fabryki, aby utworzyć list, a następnie wyświetl wynik jego wygenerowania z treścią
Thank you for your order
- Użyj fabryki, aby utworzyć raport, a następnie wyświetl wynik jego wygenerowania z treścią
Zwróć uwagę, że główny plik korzysta wyłącznie z fabryki i abstrakcyjnego typu Document — nigdy bezpośrednio nie tworzy obiektów Report, Invoice ani Letter!
Oczekiwany wynik:
=== REPORT ===
Sales increased by 25%
=============
INVOICE
--------
Widget x3 - $150
Total Due
Dear Reader,
Thank you for your order
SincerelySpróbuj swoich sił
import 'document_factory.dart';
void main() {
// TODO: Użyj DocumentFactory.create(), aby utworzyć raport
// Następnie wypisz wynik jego wygenerowania z treścią: "Sales increased by 25%"
// TODO: Wypisz pusty wiersz
// TODO: Użyj DocumentFactory.create(), aby utworzyć fakturę
// Następnie wypisz wynik jej wygenerowania z treścią: "Widget x3 - \$150"
// TODO: Wypisz pusty wiersz
// TODO: Użyj DocumentFactory.create(), aby utworzyć list
// Następnie wypisz wynik jego wygenerowania z treścią: "Thank you for your order"
}
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