Wzorzec Factory
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 72 z 91.
Wzorzec fabryki to kreacyjny wzorzec projektowy, który deleguje tworzenie obiektów do osobnej klasy lub metody. Zamiast używać bezpośrednio new w całym kodzie, prosisz fabrykę o utworzenie obiektów.
Ten wzorzec jest szczególnie przydatny, gdy masz wiele powiązanych klas, które współdzielą wspólny interfejs, i chcesz zdecydować, którą z nich utworzyć na podstawie pewnego warunku. Rozważ system powiadomień, który może wysyłać wiadomości różnymi kanałami:
<?php
interface Notification {
public function send(string $message): string;
}
class EmailNotification implements Notification {
public function send(string $message): string {
return "Email: $message";
}
}
class SmsNotification implements Notification {
public function send(string $message): string {
return "SMS: $message";
}
}
Bez fabryki porozrzucałbyś wszędzie instrukcje if i wywołania new. Fabryka centralizuje tę logikę:
<?php
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException("Unknown type: $type")
};
}
}
$notification = NotificationFactory::create('email');
echo $notification->send('Hello!');
Wynik:
Email: Hello!Kluczową zaletą jest to, że Twój kod zależy od interfejsu Notification, a nie od konkretnych klas. Jeśli później dodasz klasę PushNotification, zaktualizujesz tylko fabrykę. Cały kod korzystający z fabryki automatycznie zyska dostęp do nowego typu bez modyfikacji.
Wyzwanie
ŁatwyZbudujmy system generowania dokumentów z użyciem wzorca Factory. Różne typy dokumentów (PDF, HTML, zwykły tekst) współdzielą wspólny interfejs, ale generują różne wyniki: to idealny scenariusz do centralizacji tworzenia obiektów w fabryce.
Rozmieścisz kod w czterech plikach:
Document.php: Utwórz interfejsDocument, który definiuje kontrakt, którego muszą przestrzegać wszystkie typy dokumentów. Powinien zawierać jedną metodęrender(string $content): string, która przyjmuje treść i zwraca sformatowany dokument.Documents.php: Dołącz interfejs Document i utwórz trzy klasy, które go implementują:PdfDocument: Jego metodarender()zwraca"PDF: [content]"HtmlDocument: Jego metodarender()zwraca"<html>[content]</html>"TextDocument: Jego metodarender()zwraca"TXT: [content]"
DocumentFactory.php: Dołącz plik Documents i utwórz klasęDocumentFactoryze statyczną metodącreate(string $type): Document. Ta metoda powinna używaćmatch, aby zwracać odpowiedni obiekt dokumentu w zależności od typu:"pdf"zwraca nowy obiektPdfDocument"html"zwraca nowy obiektHtmlDocument"text"zwraca nowy obiektTextDocument- Każdy inny typ powinien zgłaszać wyjątek
InvalidArgumentExceptionz komunikatem"Unknown document type: [type]"
main.php: Dołącz plik DocumentFactory. Otrzymasz dwa dane wejściowe: typ dokumentu i treść do wyrenderowania.Użyj fabryki, aby utworzyć odpowiedni typ dokumentu, a następnie wywołaj jego metodę
render()z treścią i wypisz wynik.W nowej linii wypisz
"Factory benefit: Adding new types only requires updating the factory", aby podkreślić, dlaczego ten wzorzec jest przydatny.
Wzorzec Factory sprawia, że kod pozostaje elastyczny. Gdy później dodasz MarkdownDocument, wystarczy zaktualizować fabrykę, a cały istniejący kod nadal będzie działać bez zmian.
Spróbuj swoich sił
<?php
require_once 'DocumentFactory.php';
// Odczytaj dane wejściowe
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
// TODO: Użyj DocumentFactory, aby utworzyć dokument odpowiedniego typu
// TODO: Wywołaj metodę render() z zawartością i wypisz wynik
// TODO: W nowym wierszu wypisz "Factory benefit: Adding new types only requires updating the factory"
?>Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe $thisMetodyWłaściwościKonstruktor (__construct)Destruktor (__destruct)Powtórka — prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe parent::Przesłanianie metodSłowo kluczowe finalKlasy abstrakcyjnePowtórzenie – hierarchia pracowników7Enkapsulacja
Public, protected, privateModyfikatory dostępu w szczegółachGettery i setteryUkrywanie informacjiPromocja parametrów konstruktora (8.0)Podsumowanie — system ewidencji studentów2Przestrzenie nazw i autoloading
Wprowadzenie do przestrzeni nazwSłowo kluczowe useStandard autoloadingu PSR-4Autoloader ComposeraPodsumowanie – uporządkowany projekt5Interfejsy i kontrakty
Wprowadzenie do interfejsówImplementowanie interfejsówImplementowanie wielu interfejsówInterfejs a klasa abstrakcyjnaPodpowiadanie typów za pomocą interfejsówPodsumowanie — kalkulator kształtów8Metody magiczne
Wprowadzenie do metod magicznych__toString i __debugInfo__get, __set, __isset, __unset__call i __callStatic__clone i klonowanie obiektów__serialize i __unserializePodsumowanie — własna kolekcja11System typów i obsługa błędów
Deklaracje typówTypy nullableTypy sumy i przecięciaKlasy wyjątkówNiestandardowa hierarchia wyjątkówTry, Catch, FinallyPodsumowanie — walidator formularzy14Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Właściwości klas
Właściwości instancji a właściwości statyczneStałe w klasachMetody i właściwości statyczneWłaściwości prywatne i chronioneWłaściwości tylko do odczytu (PHP 8.1)Podsumowanie — menedżer kont bankowych6Polimorfizm
Ponowne omówienie nadpisywania metodPolimorfizm za pomocą interfejsówPodpowiedzi typów i typy sumyPóźne wiązanie statycznePodsumowanie — procesor płatności9Cechy
Wprowadzenie do cechKorzystanie z wielu cechRozwiązywanie konfliktów cechMetody abstrakcyjne w cechachCechy a dziedziczenie12Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator PHP online