Wzorzec projektowy metody fabrycznej to a twórczy wzór projektowy który zapewnia interfejs do tworzenia obiektów w nadklasie, umożliwiając podklasom zmianę typu obiektów, które zostaną utworzone. Zawiera logikę tworzenia obiektów w osobnej metodzie, promując luźne powiązanie między twórcą a tworzonymi obiektami. Ten wzorzec jest szczególnie przydatny, gdy dokładne typy tworzonych obiektów mogą się różnić lub należy je określić w czasie wykonywania, zapewniając elastyczność i rozszerzalność podczas tworzenia obiektów.
Spis treści
- Jaki jest wzorzec projektowy metody fabrycznej?
- Kiedy stosować wzorzec projektowy metody fabrycznej?
- Składniki wzorca projektowego metody fabrycznej
- Przykładowy wzór projektowy metody fabrycznej
- Przypadki użycia wzorca projektowego metody fabrycznej
- Zalety wzorca projektowego metody fabrycznej
- Wady wzorca projektowego metody fabrycznej
Jaki jest wzorzec projektowy metody fabrycznej?
Wzorzec projektowy metody fabrycznej to kreacyjny wzorzec projektowy używany w inżynierii oprogramowania w celu zapewnienia interfejsu do tworzenia obiektów w nadklasie, umożliwiając jednocześnie podklasom zmianę typu obiektów, które zostaną utworzone. Zawiera logikę tworzenia obiektu w osobnej metodzie, abstrahując proces tworzenia instancji i promując luźne powiązanie między twórcą a tworzonymi obiektami. Ten wzorzec zapewnia elastyczność, rozszerzalność i łatwość konserwacji w bazie kodu, umożliwiając podklasom definiowanie własnej implementacji metody fabrycznej w celu tworzenia określonych typów obiektów.
operatory JavaScript
Kiedy stosować wzorzec projektowy metody fabrycznej?
Użyj wzorca projektowego metody fabrycznej:
- Jeśli chcesz enkapsulować tworzenie obiektu: Jeśli masz złożony proces tworzenia obiektów lub proces może się różnić w zależności od warunków, hermetyzacja tej logiki w metodzie fabrycznej może uprościć kod klienta i promować możliwość ponownego użycia.
- Jeśli chcesz oddzielić kod klienta od konkretnych klas: Korzystanie ze wzorca metody fabrycznej umożliwia tworzenie obiektów za pośrednictwem interfejsu lub klasy abstrakcyjnej, wyodrębniając szczegółowe szczegóły implementacji konkretnych klas z kodu klienta. Sprzyja to luźnemu powiązaniu i ułatwia modyfikowanie lub rozszerzanie systemu bez wpływu na istniejący kod klienta.
- Jeśli potrzebujesz obsługi wielu odmian produktu: Jeśli w Twojej aplikacji konieczne jest utworzenie różnych odmian produktu lub jeśli w przyszłości mogą zostać wprowadzone nowe typy produktów, Wzorzec metody fabrycznej zapewnia elastyczny sposób uwzględnienia tych odmian poprzez zdefiniowanie metod fabrycznych dla każdego typu produktu.
- Jeśli chcesz wspierać dostosowywanie lub konfigurację: Fabryki mogą służyć do hermetyzacji logiki konfiguracji, umożliwiając klientom dostosowywanie procesu tworzenia poprzez dostarczanie parametrów lub opcji konfiguracji do metody fabryki.
Składniki wzorca projektowego metody fabrycznej
1. Stwórca
Jest to klasa abstrakcyjna lub interfejs deklarujący metodę fabryczną. Kreator zazwyczaj zawiera metodę, która służy jako fabryka do tworzenia obiektów. Może zawierać także inne metody współpracujące z utworzonymi obiektami.
mapa w Javie
2. Twórca betonu
Klasy Concrete Creator to podklasy Creatora, które implementują metodę fabryczną do tworzenia określonych typów obiektów. Każdy Twórca Betonu jest odpowiedzialny za stworzenie konkretnego produktu.
3. Produkt
Jest to interfejs lub klasa abstrakcyjna dla obiektów tworzonych przez metodę fabryki. Produkt definiuje wspólny interfejs dla wszystkich obiektów, które może utworzyć metoda fabryczna.
4. Produkt betonowy
Klasy produktów betonowych to rzeczywiste obiekty tworzone za pomocą metody fabryki. Każda klasa Concrete Product implementuje interfejs Product lub rozszerza klasę abstrakcyjną Product.
Przykładowy wzór projektowy metody fabrycznej
Poniżej znajduje się opis problemu umożliwiający zrozumienie wzorca projektowego metody fabrycznej:
Rozważmy aplikację, która musi obsługiwać tworzenie różnych typów pojazdów, takich jak dwukołowe, trójkołowe i czterokołowe. Każdy typ pojazdu ma swoje specyficzne właściwości i zachowania.
1. Bez wzorca projektowego metody fabrycznej
Jawa /*package whatever //do not write package name here */ import java.io.*; // Library classes abstract class Vehicle { public abstract void printVehicle(); } class TwoWheeler extends Vehicle { public void printVehicle() { System.out.println('I am two wheeler'); } } class FourWheeler extends Vehicle { public void printVehicle() { System.out.println('I am four wheeler'); } } // Client (or user) class class Client { private Vehicle pVehicle; public Client(int type) { if (type == 1) { pVehicle = new TwoWheeler(); } else if (type == 2) { pVehicle = new FourWheeler(); } else { pVehicle = null; } } public void cleanup() { if (pVehicle != null) { pVehicle = null; } } public Vehicle getVehicle() { return pVehicle; } } // Driver program public class GFG { public static void main(String[] args) { Client pClient = new Client(1); Vehicle pVehicle = pClient.getVehicle(); if (pVehicle != null) { pVehicle.printVehicle(); } pClient.cleanup(); } }> Wyjście I am two wheeler>
Jakie są problemy z powyższym projektem?
W powyższym projekcie kodu:
- Ciasne sprzęgło: Klasa klienta
Client>bezpośrednio tworzy instancje konkretnych klas (TwoWheeler>IFourWheeler>) w oparciu o typ danych wejściowych dostarczonych podczas jego konstrukcji. Prowadzi to do ścisłego powiązania między klientem a konkretnymi klasami, co utrudnia utrzymanie i rozszerzanie kodu. - Naruszenie zasady pojedynczej odpowiedzialności (SRP): The
Client>klasa jest odpowiedzialna nie tylko za określenie typu pojazdu, który ma zostać utworzony w oparciu o typ danych wejściowych, ale także za zarządzanie cyklem życia obiektu pojazdu (np. czyszczenie). Narusza to zasadę pojedynczej odpowiedzialności, która stanowi, że klasa powinna mieć tylko jeden powód do zmiany. - Ograniczona skalowalność: Dodanie nowego typu pojazdu wymaga modyfikacji pliku
Client>class, co narusza zasadę Open-Closed. Ten projekt nie jest skalowalny, ponieważ nie może obsługiwać nowych typów pojazdów bez modyfikacji istniejącego kodu.
Jak uniknąć problemu?
- Zdefiniuj interfejs fabryczny: Stwórz
VehicleFactory>interfejs lub klasa abstrakcyjna z metodą tworzenia pojazdów. - Wdrażaj fabryki betonu: Implementuj klasy fabryki betonu (
TwoWheelerFactory>IFourWheelerFactory>), które implementująVehicleFactory>interfejs i zapewniają metody tworzenia instancji określonych typów pojazdów. - Klient refaktoryzacji: Zmodyfikuj
Client>klasa, aby zaakceptować aVehicleFactory>instancję zamiast bezpośrednio tworzyć instancje pojazdów. Klient zażąda pojazdu z fabryki, eliminując potrzebę stosowania logiki warunkowej opartej na typie pojazdu. - Większa elastyczność: Dzięki takiemu podejściu dodawanie nowych typów pojazdów jest tak proste, jak utworzenie nowej klasy fabrycznej dla nowego typu pojazdu bez modyfikowania istniejącego kodu klienta.
2. Z wzorcem projektowym metody fabrycznej
Podzielmy kod na kod komponentowy:

1. Interfejs produktu
Jawa // Product interface representing a vehicle public abstract class Vehicle { public abstract void printVehicle(); }> 2. Produkty betonowe
Jawa // Concrete product classes representing different types of vehicles public class TwoWheeler extends Vehicle { public void printVehicle() { System.out.println('I am two wheeler'); } } public class FourWheeler extends Vehicle { public void printVehicle() { System.out.println('I am four wheeler'); } }> 3. Interfejs twórcy (interfejs fabryczny)
Jawa // Factory interface defining the factory method public interface VehicleFactory { Vehicle createVehicle(); }> 4. Twórcy betonu (fabryki betonu)
Jawa // Concrete factory class for TwoWheeler public class TwoWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new TwoWheeler(); } } // Concrete factory class for FourWheeler public class FourWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new FourWheeler(); } }> Kompletny kod tego przykładu:
Jawa // Library classes abstract class Vehicle { public abstract void printVehicle(); } class TwoWheeler extends Vehicle { public void printVehicle() { System.out.println('I am two wheeler'); } } class FourWheeler extends Vehicle { public void printVehicle() { System.out.println('I am four wheeler'); } } // Factory Interface interface VehicleFactory { Vehicle createVehicle(); } // Concrete Factory for TwoWheeler class TwoWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new TwoWheeler(); } } // Concrete Factory for FourWheeler class FourWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new FourWheeler(); } } // Client class class Client { private Vehicle pVehicle; public Client(VehicleFactory factory) { pVehicle = factory.createVehicle(); } public Vehicle getVehicle() { return pVehicle; } } // Driver program public class GFG { public static void main(String[] args) { VehicleFactory twoWheelerFactory = new TwoWheelerFactory(); Client twoWheelerClient = new Client(twoWheelerFactory); Vehicle twoWheeler = twoWheelerClient.getVehicle(); twoWheeler.printVehicle(); VehicleFactory fourWheelerFactory = new FourWheelerFactory(); Client fourWheelerClient = new Client(fourWheelerFactory); Vehicle fourWheeler = fourWheelerClient.getVehicle(); fourWheeler.printVehicle(); } }> Wyjście I am two wheeler I am four wheeler>
W powyższym kodzie:
wystawianie Javy
-
Vehicle>służy jako interfejs produktu, definiując wspólną metodęprintVehicle()>które muszą spełniać wszystkie produkty betonowe. -
TwoWheeler>IFourWheeler>to konkretne klasy produktów reprezentujące różne typy pojazdów, realizujące tzwprintVehicle()>metoda. -
VehicleFactory>pełni funkcję interfejsu kreatora (interfejs fabryczny) z metodącreateVehicle()>reprezentującą metodę fabryczną. -
TwoWheelerFactory>IFourWheelerFactory>to klasy twórców betonu (Betonowe Fabryki) realizująceVehicleFactory>interfejs do tworzenia instancji określonych typów pojazdów.
Przypadki użycia wzorca projektowego metody fabrycznej
Oto kilka typowych zastosowań wzorca projektowania metody fabrycznej:
- Ramy twórcze:
- JDBC (Java Database Connectivity) szeroko wykorzystuje fabryki do tworzenia połączeń, instrukcji i zestawów wyników. Frameworki wstrzykiwania zależności, takie jak Spring i Guice, w dużym stopniu opierają się na fabrykach do tworzenia komponentów bean i zarządzania nimi.
- Zestawy narzędzi GUI:
- Swing i JavaFX wykorzystują fabryki do tworzenia komponentów interfejsu użytkownika, takich jak przyciski, pola tekstowe i etykiety, co pozwala na dostosowywanie i elastyczność projektowania interfejsu użytkownika.
- Ramy rejestrowania:
- Struktury rejestrowania, takie jak Log4j i Logback, wykorzystują fabryki do tworzenia rejestratorów o różnych konfiguracjach, umożliwiając kontrolę nad poziomami rejestrowania i miejscami docelowymi danych wyjściowych.
- Serializacja i deserializacja:
- Struktury serializacji obiektów często wykorzystują fabryki do tworzenia obiektów na podstawie serializowanych danych, obsługując różne formaty serializacji i wersjonowanie.
- Systemy wtyczek:
- Systemy oparte na wtyczkach często korzystają z fabryk do dynamicznego ładowania i tworzenia instancji wtyczek, co pozwala na rozszerzalność i dostosowywanie.
- Produkcja gier:
- Silniki gier często wykorzystują fabryki do tworzenia różnych typów obiektów, postaci i poziomów gier, promując organizację kodu i elastyczność.
- Tworzenie stron internetowych:
- Struktury internetowe czasami wykorzystują fabryki do tworzenia komponentów widoków, kontrolerów i usług, umożliwiając modułowość i testowalność w aplikacjach internetowych.
Zalety wzorca projektowego metody fabrycznej
Zalety wzorca projektowego metody fabrycznej to:
Dekodowanie base64 w js
- Odsprzęganie: Oddziela logikę tworzenia obiektów od kodu klienta korzystającego z tych obiektów. Dzięki temu kod jest bardziej elastyczny i łatwiejszy w utrzymaniu, ponieważ zmiany w procesie tworzenia nie wymagają modyfikacji kodu klienta.
- Rozciągliwość: Wprowadzanie nowych typów produktów jest łatwe bez zmiany kodu klienta. Wystarczy utworzyć nową podklasę Concrete Creator i wdrożyć metodę fabryczną, aby wyprodukować nowy produkt.
- Testowalność: Upraszcza testowanie jednostkowe, umożliwiając wyśmiewanie lub pomijanie procesu tworzenia produktu podczas testów. Możesz testować różne implementacje produktów w izolacji, bez polegania na rzeczywistym tworzeniu obiektów.
- Możliwość ponownego wykorzystania kodu: Metodę fabryczną można ponownie wykorzystać w różnych częściach aplikacji, gdzie potrzebne jest utworzenie obiektu. Promuje to centralizację i ponowne wykorzystanie logiki tworzenia obiektów.
- Kapsułkowanie: Ukrywa konkretne klasy produktów przed kodem klienta, czyniąc kod mniej zależnym od konkretnych implementacji. Poprawia to łatwość konserwacji i zmniejsza sprzężenie.
Wady wzorca projektowego metody fabrycznej
Wadami wzorca projektowego metody fabrycznej są:
- Zwiększona złożoność: Wprowadza dodatkowe klasy i interfejsy, dodając warstwę abstrakcji, która może sprawić, że kod będzie bardziej skomplikowany w zrozumieniu i utrzymaniu, szczególnie dla osób niezaznajomionych ze wzorcem.
- Nad głową: Użycie polimorfizmu i wiązania dynamicznego może nieznacznie wpłynąć na wydajność, chociaż w większości zastosowań jest to często nieistotne.
- Ścisłe powiązanie w ramach hierarchii produktów: Twórcy betonu są nadal ściśle powiązani z odpowiadającymi im produktami betonowymi. Zmiany w jednym często pociągają za sobą konieczność zmiany w drugim.
- Zależność od podklas betonowych: Kod klienta w dalszym ciągu zależy od abstrakcyjnej klasy Creator, co wymaga znajomości jej konkretnych podklas w celu prawidłowego wywołania metod fabrycznych.
- Możliwość nadmiernego użycia: Ważne jest, aby używać wzorca Metody fabrycznej w sposób rozsądny, aby uniknąć nadmiernego projektowania aplikacji. Proste tworzenie obiektów często można wykonać bezpośrednio, bez potrzeby tworzenia fabryki.
- Wyzwania testowe: Testowanie samej logiki fabrycznej może być bardziej złożone.