Wprowadzenie

Wzorzec projektowy Fabryka należy do grupy wzorców kreacyjnych i służy do tworzenia obiektów bez konieczności bezpośredniego określania ich konkretnych klas.
Innymi słowy, Fabryka pozwala „zlecić” tworzenie obiektów specjalnym klasom, które wiedzą, jak i jaki konkretny obiekt należy utworzyć.
W praktyce oznacza to, że kod korzystający z obiektów nie musi wiedzieć, jak są one tworzone – wystarczy, że poprosi Fabrykę o produkt.
Idea wzorca Fabryka
Główna idea wzorca Fabryka polega na delegowaniu procesu tworzenia obiektów do specjalnych metod lub klas.
Zamiast tworzyć obiekty za pomocą operatora new, korzystamy z metody fabrykującej, która zwraca odpowiedni typ produktu.
Dzięki temu możemy łatwo rozszerzać system o nowe typy obiektów bez modyfikowania istniejącego kodu – wystarczy dodać nową klasę produktu i jej fabrykę.
Kluczowe elementy wzorca:
ConcreteCreator (Konkretny Twórca) – implementacja metody fabrykującej, tworząca określony produkt.
Product (Produkt) – interfejs lub klasa bazowa dla obiektów tworzonych przez fabrykę,
ConcreteProduct (Konkretny Produkt) – konkretna implementacja produktu,
Creator (Twórca) – klasa deklarująca metodę fabrykującą,

Przykład z prefabrykacji żelbetowej

Wyobraźmy sobie zakład prefabrykacji, który produkuje różne typy elementów żelbetowych:
- Słupy,
- Belki,
- Płyty stropowe,
- Ściany prefabrykowane.
Każdy z tych elementów ma swoje parametry, ale ich tworzenie odbywa się w ramach wspólnego procesu – zbrojenie, formowanie, wylewanie betonu, pielęgnacja, kontrola jakości itd.
W tym przypadku Fabryka może być odpowiedzialna za tworzenie odpowiedniego typu elementu w zależności od zapotrzebowania. Przykładowo, klient może poprosić o „belkę”, a fabryka zwróci gotowy obiekt klasy BelkaPrefabrykowana.
Poniżej przykład zastosowania wzorca Fabryka w kontekście prefabrykacji żelbetowej:
// Produkt – wspólny interfejs prefabrykatów
interface PrefabElement {
void produkcja();
}
// Konkretne produkty
class Slup implements PrefabElement {
@Override
public void produkcja() {
System.out.println("Produkcja słupa żelbetowego: zbrojenie, szalowanie, betonowanie.");
}
}
class Belka implements PrefabElement {
@Override
public void produkcja() {
System.out.println("Produkcja belki prefabrykowanej: zbrojenie, forma, pielęgnacja betonu.");
}
}
class Plyta implements PrefabElement {
@Override
public void produkcja() {
System.out.println("Produkcja płyty stropowej: zbrojenie siatką, betonowanie, wygładzanie powierzchni.");
}
}
// Twórca (fabryka)
abstract class PrefabFactory {
public abstract PrefabElement utworzPrefabElement();
// Szablon metody produkcji
public void procesProdukcji() {
PrefabElement element = utworzPrefabElement();
element.produkcja();
System.out.println("Kontrola jakości i przygotowanie do transportu.\n");
}
}
// Konkretne fabryki
class SlupFactory extends PrefabFactory {
@Override
public PrefabElement utworzPrefabElement() {
return new Slup();
}
}
class BelkaFactory extends PrefabFactory {
@Override
public PrefabElement utworzPrefabElement() {
return new Belka();
}
}
class PlytaFactory extends PrefabFactory {
@Override
public PrefabElement utworzPrefabElement() {
return new Plyta();
}
}
// Klasa testowa
public class Main {
public static void main(String[] args) {
PrefabFactory slupFabryka = new SlupFactory();
PrefabFactory belkaFabryka = new BelkaFactory();
PrefabFactory plytaFabryka = new PlytaFactory();
slupFabryka.procesProdukcji();
belkaFabryka.procesProdukcji();
plytaFabryka.procesProdukcji();
}
}
Zalety tego podejścia

Elastyczność – łatwe dodawanie nowych typów prefabrykatów (np. „ściana” czy „fundament”) bez zmiany istniejącego kodu,
Hermetyzacja logiki tworzenia – szczegóły budowy elementów są ukryte w fabrykach,
Zgodność z zasadą otwarte-zamknięte (OCP) – można rozszerzać funkcjonalność bez modyfikowania istniejących klas,
Łatwiejsze testowanie – poszczególne fabryki można testować niezależnie.
Wady

Wzrost liczby klas – każda nowa kategoria produktu wymaga stworzenia nowej fabryki,
Dodatkowa warstwa pośrednia – dla prostych systemów może być nadmiarowa,
Potrzeba dobrej struktury dziedziczenia – niepoprawne zaprojektowanie hierarchii produktów i fabryk może prowadzić do trudnej w utrzymaniu architektury
