Metoda Wytwórcza, znana również jako Factory Method, jest jednym z najważniejszych wzorców kreacyjnych w projektowaniu oprogramowania. Zapewnia ona elastyczność i ponowne wykorzystanie kodu, co jest kluczowe w tworzeniu skalowalnych i łatwych do utrzymania aplikacji. W tym artykule dokładnie omówimy, czym jest metoda wytwórcza, kiedy powinniśmy ją stosować oraz jakie problemy pomaga rozwiązać. Ponadto, zilustrujemy jej zastosowanie za pomocą przykładu kodu.
Czym jest Metoda Wytwórcza?
Metoda Wytwórcza to wzorzec projektowy, który udostępnia interfejs do tworzenia obiektów w ramach klasy bazowej, ale pozwala podklasom zmieniać typ tworzonych obiektów. Oznacza to, że zamiast tworzyć obiekty bezpośrednio za pomocą operatora new, klasa bazowa deleguje tworzenie obiektów do metod wytwórczych, które mogą być nadpisane przez podklasy.
Zalety Metody Wytwórczej
- Elastyczność: Pozwala tworzyć obiekty w sposób dynamiczny, bez konieczności zmiany kodu w całej aplikacji.
- Ponowne Użycie Kodów: Dzięki oddzieleniu procesu tworzenia obiektów od ich użycia, można ponownie wykorzystać istniejące klasy w innych kontekstach.
- Zapewnienie Jednolitego Interfejsu: Cały proces tworzenia obiektów jest ukryty za jednolitym interfejsem, co ułatwia utrzymanie i rozwijanie systemu.
Kiedy stosować?
Metoda Wytwórcza jest szczególnie przydatna w sytuacjach, gdy:
- Klasa nie może przewidzieć, jaki typ obiektów powinna stworzyć.
- Klasa chce delegować odpowiedzialność za tworzenie obiektów do swoich podklas.
- W aplikacji istnieje wiele podobnych klas różniących się tylko w sposobie, w jaki tworzą obiekty.
Przykład Zastosowania Metody Wytwórczej
Rozważmy scenariusz, w którym tworzymy system do przygotowywania posiłków. System ten może tworzyć różne typy posiłków, takie jak Pizza oraz Sałatka, w zależności od wymagań klienta. Zamiast bezpośrednio tworzyć obiekty Pizza lub Sałatka, zastosujemy metodę wytwórczą.
// Interfejs Product
interface Posilek {
void przygotuj();
}// Konkretne produkty
class Pizza implements Posilek {
@Override
public void przygotuj() {
System.out.println("Przygotowanie pizzy…");
}
}class Salatka implements Posilek {
@Override
public void przygotuj() {
System.out.println("Przygotowanie sałatki…");
}
}// Klasa bazowa z metodą wytwórczą
abstract class PrzygotowaniePosilkow {
// Deklaracja metody wytwórczej
public abstract Posilek utworzPosilek();// Operacja na produkcie
public void przygotujPosilek() {
Posilek posilek = utworzPosilek();
posilek.przygotuj();
}
}// Konkretne klasy implementujące metodę wytwórczą
class PrzygotowaniePizzy extends PrzygotowaniePosilkow {
@Override
public Posilek utworzPosilek() {
return new Pizza();
}
}class PrzygotowanieSalatki extends PrzygotowaniePosilkow {
@Override
public Posilek utworzPosilek() {
return new Salatka();
}
}// Klasa klienta
public class Restauracja {
public static void main(String[] args) {
PrzygotowaniePosilkow przygotowaniePizzy = new PrzygotowaniePizzy();
przygotowaniePizzy.przygotujPosilek();PrzygotowaniePosilkow przygotowanieSalatki = new PrzygotowanieSalatki();
przygotowanieSalatki.przygotujPosilek();
}
}
W powyższym przykładzie mamy interfejs Posilek, który jest implementowany przez klasy Pizza oraz Sałatka. Klasa bazowa PrzygotowaniePosilkow zawiera metodę wytwórczą utworzPosilek(), którą nadpisują klasy konkretne PrzygotowaniePizzy i PrzygotowanieSalatki. Klasa Restauracja demonstruje, jak można użyć metody wytwórczej do dynamicznego tworzenia i przygotowywania posiłków bez konieczności wiedzy o ich konkretnych typach.
Podsumowanie
Metoda Wytwórcza jest potężnym narzędziem, które pozwala na dynamiczne tworzenie obiektów i delegowanie tej odpowiedzialności do podklas. Dzięki temu wzorcowi możemy zachować elastyczność, lepszą organizację kodu oraz możliwość ponownego wykorzystania istniejących rozwiązań w różnych kontekstach. Możliwość łatwego rozszerzania systemu o nowe typy obiektów bez konieczności modyfikowania istniejących klas to jedna z najważniejszych zalet tego wzorca.