Fabryka abstrakcyjna (ang. Abstract factory) (wzorzec kreacyjny) dostarcza interfejs do tworzenia powiązanych bądź zależnych obiektów różnych typów bez dokładnej znajomości ich klas. Fabryka abstrakcyjna definiuje rodzinę produktów możliwych do wygenerowania z danej fabryki. Konkretne fabryki mają za zadanie zdecydować o typie i stworzyć obiekty z jednej rodziny produktów. Implementacja wzorca Fabryki abstrakcyjnej może być utożsamiana ze zbiorem Metod wytwórczych dla każdej abstrakcji produktu. Jednakże w przeciwieństwie do Metody wytwórczej, której celem jest tworzenie obiektów o jednym wspólnym typie, Fabryka abstrakcyjna realizuje zadanie tworzenia rodziny powiązanych ze sobą obiektów. Proces inicjalizacji obiektów jest centralizowany, kod otwarty na zmiany, a klient odizolowany od szczegółów implementacji rodziny produktów. Klient nie musi znać typów tworzonych produktów, ponieważ cała odpowiedzialność spoczywa na fabryce. Spełnia zasadę OCP - otwarte/zamknięte, a także DIP - odwrócenia zależności.
Ograniczenia
Wprowadzenie nowego abstrakcyjnego produktu do rodziny produktów wymusza rozbudowę wszystkich fabryk o metodę zwracającą kolejną abstrakcje, natomiast dodanie nowego typu pociąga za sobą modyfikację metod w niektórych fabrykach. W przypadku małych projektów użycie wzorca może być przesadnę co w rezultacie zwiększy złożoność kodu.
Użycie
Fabryka abstrakcyjna znajduje zastosowanie tam, gdzie zachodzi potrzeba tworzenia zbioru powiązanych ze sobą produktów o wspólnych typach, ale różnej implementacji, a klient ma być zwolniony ze znajomości szczegółów implementacji. Ponadto dokładne typy obiektów nie muszą być znane w trakcie tworzenia kodu, a decyzja o tym jakie obiekty zostaną wygenerowane zapada dynamicznie.
Implementacja
Konkretna fabryka implementuje abstrakcyjną fabrykę AbstractFactory, która deklaruje dostarczenie grupy produktów ze sobą powiązanych. Każda fabryka odpowiada za stworzenie produktów na swój ustalony sposób. Produkty rozszerzają klasę abstrakcyjną produktu AbstractProduct lub implementują jej interfejs.
Poniższy listing przedstawia implementację fabryki abstrakcyjnej AbstractFactory w oparciu o dwie fabrykie FactoryA, FactoryB i dwie rodziny produktów AbstractProduct1, AbstractProduct2.
Klient decyduje z której fabryki skorzystać w celu wygenerowania obiektów. Obiekty można generować bezpośrednio z fabryki lub przekazać do obiektu docelowego fabrykę jako parametr konstruktora.
Przykład
Sklep internetowy JerseySport prowadzi sprzedaż zestawów odzieżowych Jersey (skarpetki Socks, spodenki Shorts, koszulka Shirt) dla różnych dyscyplin sportu. Klient może skonfigurować zestawy pod względem rozmiaru, koloru oraz dla niektórych dyscyplin także długości rękawków koszulek. Ze względu na mnogość konfiguracji parametrów odzieży oraz ich przeznaczenia, sposób składania zamówienia realizowany jest poprzez wzorzec Fabryki abstrakcyjnej. Klasa reprezentująca kompletny sportowy zestaw odzieży wraz ze strukturą poszczególnych elementów zestawu przedstawiona jest na poniższym listingu.
Elementy zestawu odzieżowego Socks, Shorts, Shirt w zależności od sportu różnią się ceną, właściwościami oraz sposobem sprawdzania dostępności. W związku z tym dla każdej dyscypliny sportowej tworzona jest dedykowana konfiguracja elementów zestawu odzieżowego. Poniższy listing przedstawia implementacje dla piłkarskiej odzieży.
Do składania kompletnego zestawu służą dedykowane dla każdej dyscypliny sportu fabryki (FootballFactory, BasketballFactory itp) implementujące abstrakcyjnę fabrykę JerseyFactory.
Proces kompletowania zamówienia przez klienta może przebiegać następująco.
Biblioteki
Ze względu na specyfikację wzorca, implementacja Fabryka abstrakcyjna spoczywa na programiście.