Fabryka Abstrakcyjna – Wzorzec Projektowy (Abstract Factory)

Fabryka Abstrakcyjna (ang. Abstract Factory) – wzorzec projektowy. Przykład zastosowania oparty na historii w celu łatwiejszego zrozumienia tego wzorca dla laika.

James miał firmę, która zajmowała się składaniem i sprzedawaniem hulajnóg. Hulajnoga składa się z czterech elementów: kierownicy, kolek, hamulca i naklejki. Firma podzespoły do hulajnóg kupowała u chińskiego producenta. Chiński producent części miał fabrykę, która specjalizowała się w wytwarzaniu produktów tylko do hulajnóg.

James jako stały klient, został zaproszony do chińskiej fabryki (konkretnej fabryki). Tam miał możliwość zobaczyć jak produkowane są poszczególne części do hulajnogi.

James nie miał problemów z kupowaniem części u chińskiego producenta.

Chiński producent był tani, bo jego komponenty nie były najwyższej jakości. James na początku z powodzeniem stosował chińskie elementy w budowaniu hulajnóg na sprzedaż. Po pewnym czasie James postanowił wprowadzić droższa wersje hulajnogi. Chińska fabryka nie mogła mu zapewnić części, jakie chciał mieć James do budowy lepszej hulajnogi. James znalazł Polską fabrykę (konkretną fabrykę), która tworzyła elementy do droższej wersji hulajnogi. Pojechał więc do Wrocławia, gdzie mieściła się fabryka, aby zobaczyć jak produkowane są komponenty do hulajnogi.

James zaczął z powodzenie zamawiać także polskie komponenty do hulanóg.

W tym momencie James składał dwie wersje hulajnóg: tańsze i droższe. Części do hulajnóg ściągał z fabryki chińskiej oraz fabryki wrocławskiej.

Refactoring

Spójrzmy na kod. Czy widzisz, co można byłoby tutaj udoskonalić?
Klasa klient ma osobna pola na produkty z Chin i produkty z Polski. Kółka to kółka. Nie zależnie czy są z Chin z Polski. Jak można rozwiązać ten problem?
Weźmy pod lupę klasy PolskieKolka oraz ChinskieKolka. Są takie same. Usuńmy tą niepotrzebną redundancje. Stwórzmy zamiast klas PolskieKolka oraz ChinskieKolka klasę Kolka.

Poprawny kod PolskiejFabryki i ChinskiejFabryki.

I zobaczmy jak James może teraz zamawiać nowe produkty:

Ale co się w tym momencie będzie dziać? James będzie zawiedziony. To czy kółka pochodzą z polskiej fabryki czy z chińskiej fabryki będzie można rozpoznać tylko po kolorze kółek. A co jak Polacy będą produkować czarne kółka? Nie rozpoznamy w późniejszym etapie, kto wyprodukował czarne kółka. Wiec rozwiążmy ten problem inaczej.

Co dało nam to, że dodaliśmy klasę abstrakcyjną, dziedziczenie? Zobaczmy jak James teraz może zamawiać kółka.

Teraz James może zamówić dowolny typ kółek, a to co wyprodukuje zapisać do zmiennej _kolka. Dziedziczenie idealnie nadaje się dla tego przypadku.
Skoro takie rozwiązanie dobrze się sprawdza to zastosujmy dziedzicznie dla pozostałych elementów.

Klasy polskich produktów:

Klasy chińskich produktów.

W fabrykach trzeba zmienić klasy jakie zwracają poszczególne metody.

W klasie Klient usuwamy zbędne pola i piszemy uniwersalne pola.

Jak widać to, że zostały wprowadzone klasy abstrakcyjne dla poszczególnych produktów daje nam możliwość pozbycia się dużej ilości pół w klasie Klient.

Co tutaj jeszcze można poprawić? Metody ZamowPolskieElementy oraz ZamowChinskieElementy nie wyglądają tak źle. No ale co jakby James zamawiał z 50 różnych fabryk elementy? Pisać 50 różnych metod? Troszkę za dużo. Polska i Chińska fabryka nie różnią się nazwami metod. Wprowadźmy ich dodatkowy element abstrakcji. Może interfejs? Można. Ale skoro nazwa tego wzorca projektowego to fabryka abstrakcyjna to wprowadźmy klasę abstrakcyjną.

Poprawmy kod obydwu fabryk:

I zobaczmy jak teraz James może zamawiać nowe produkty.

James jako klient ma teraz do dyspozycji wszystkie niezbędne elementy do produkcji hulajnogi. Co może z nimi zrobić? Na przykład może sprawdzić wysokość kierownicy.

Sprawdźmy jak to będzie działać w praktyce.

Trochę teorii:

Poniższy diagram UML przedstawia wzorzec projektowy Fabryka Abstrakcyjna.

abstractFactory
Źródło: www.dofactory.com

Odnieśmy ten diagram UML do naszego przykładu.

Klient jako Client
FabrykaAbstrakcyjna jako AbstractFactory
ChinskaFabryka jako ConcretFactory1
PolskaFabryka jako ConcretFactory2
Kolka jako AbstractProductA
ChinskieKolka jako ProductA1
PolskieKolka jako ProductA2
Kierownica jako AbstractProductB
ChinskaKierownica jako ProductB1
PolskaKierownica jako ProductB2

Wzorzec ten został opisany przez Bandę Czworga (Gang of Four). Wzorzec projektowy Fabryka Abstrakcyjna należy do wzorców kreacyjnych. Problem, który pomaga rozwiązać Fabryka Abstrakcyjna dotyczy implantacji klas. W momencie kiedy w programie klasy posiadają wiele różnych implementacji, fabryki mają za zadanie zgrupować różne implementacje obiektów i je stworzyć. Fabryki tworzą instancje klas, które pochodzą z jednej rodziny – czyli w naszym przykładzie jedna fabryka odpowiada za stworzenie obiektów z polskich rodziny, a druga z chińskiej rodziny.

Codeproject – przykład 1 (ang)
Codeproject – przykład 2 (ang)
DoFactory – przykład (ang)
Wikipedia (ang)
Dotnetpage – przykład (pl)
Siszarp – przykład (pl)

Powered by: Wordpress