=====Abstract factory pattern (Fabryka abstrakcyjna)===== /************************************************************************************* * Michał Chodkiewicz * * Wzorzec: fabryka abstrakcyjna (abstract factory) * * * * Zastosowanie: Wzorzec ten umożliwia łatwe wprowadzanie zmian w zakresie klas * * używanych w kodzie, co umożliwia pisanie kodu, np: na kilka * * platform jednocześnie, czy łatwiejsze zmienianie kodu wewnątrz * * klasy bibliotecznej. * * * * Opis: Fabryka abstrakcyjna, zwykle tworzona jako interfejs, w języku * * c++ jest implementowana za pomocą klasy abstrakcyjnej. Klasa ta * * ma wygląd typowej fabryki, jednak jako typy zwracane przez * * wirtualne metody fabrykujące ma zadeklarowane klasy abstrakcyjne * * reprezentujące interfejsy obiektów zwracanych przez klasy * * pochodne. W kodzie programu implementuje się dla konkretnych * * zastosowań klasy pochodne od fabryki abstrakcyjnej wytwarzające * * obiekty odpowiednie dla danego systemu czy pliku * * konfiguracyjnego. Dzięki temu, że najczęściej fabryka jest * * tworzona w programie tylko raz, przy zmianie zachowania obiektów * * wystarczy zmodyfikować tą linijkę w kodzie, w której następuje * * przypisanie konkretnej fabryki. * * * * Przykładowy schemat (schemat opisuje inny przypadek niż kod, dla urozmaicenia): * * Prezentowany jest przypadek programowania dla kilku systemów operacyjnych * * * * Odczyt schematu: * * [Element na początku strzałki] * * (d) dziedziczy po * * (w) zawiera wskaźnik/wskaźniki na * * (t) tworzy obiekty klasy * * [Element na który wskazuje strzałka] * * _______________ ______________________ * * | KlasaUsera |-------------->|FabrykaAbstrakcyjna | * * |_____________| (w)|____________________| * * |_____________| |____________________| * * |_____________| | A stworzObiekt()=0 | * * | |____________________| * * | /|\(d) /|\(d) /|\(d) * * | ______________| | |________ * * | _______|__________ __________|_______ ________|_________* * | |FabrykaUnixowa | |FabrykaDosowa | |FabrykaWindows |* * -----------------/\----|________________| |________________| |________________|* * | | |________________| |________________| |________________|* * | | |A stworzObiekt()| |A stworzObiekt()| |A stworzObiekt()|* * | |(w) |________________| |________________| |________________|* * | ___________\|/_____ | | * * | | A (klasa abstr) | | | * * | |_________________| | | * * | |_________________| | | * * | | zareaguj() | | | * * | |_________________| | | * * | /|\(d) /|\(d) /|\(d) | | * * |(t)___| | |_______ | | * * \|/__|______ ___|________ _____|______ | | * * | AUnix | | ADos | | AWindows | | | * * |__________| |__________| |__________| (t) | | * * |__________| |__________| |__________|<-------------/\-----------------| * * |zareaguj()| |zareaguj()| |zareaguj()| | * * |__________| |__________| |__________| | * * /|\(t) | * * |________________________________| * * * *************************************************************************************/ /* Przykładowy kod. Przedstawia on rysowanie obiektów w zależności od szybkości procesora */ #include //Biblioteka potrzebna w tym przykładzie using namespace std;// dla wygody, żeby nie pisać wszędzie std // Abstrakcyjny model obiektu graficznego class ObiektGraficznyAbstrakcyjny { protected: float x_;// położenie na ekranie w osi x float y_;// położenie na ekranie w osi y public: virtual void rysujSie()=0;// metoda do rysowania obiekt // poniższe metody są wirtualne, gdyż klasy pochodne nie muszą koniecznie w ten sposób przechowywać // położenia obiektu, jednak mają już ciała, gdyż to będzie najczęstszy przypadek // metoda do ustalania położenia obiektu virtual void ustawPozycje(float x, float y){ x_=x; y_=y; } // metody do pobierania położenia obiektu virtual float podajPozX() {return x_;} virtual float podajPozY() {return y_;} ObiektGraficznyAbstrakcyjny (float x, float y) : x_(x), y_(y){} virtual ~ObiektGraficznyAbstrakcyjny() {}//wirtualny destruktor, bo są wirtualne funkcje }; // Abstrakcyjna fabryka obiektów, służąca za interfejs class FabrykaObiektowGraficznychAbstrakcyjna { public: // metoda do tworzenia instancji obiektów virtual ObiektGraficznyAbstrakcyjny * utworzObiekt(float x, float y)=0; virtual ~FabrykaObiektowGraficznychAbstrakcyjna(){}//wirtualny destruktor, bo są wirtualne funkcje }; // Konkretny model obiektu graficznego, dla wolniejszych komputerów class ObiektGraficznyProsty : public ObiektGraficznyAbstrakcyjny { public: // funkcja rysujSie jest mocno okrojona, gdyż to tylko przykład zastosowania void rysujSie(){ cout<<"malo wymagajacy model jest rysowany na pozycji: "<utworzObiekt(temp->podajPozX(), temp->podajPozY()); delete temp; } else if (nowaPartia){ pulaObiektow_[licznik]=fabryka_->utworzObiekt(licznik, ILE_OBIEKTOW - licznik); } } } // dla ustawienia źródła obiektów void ustawFabryke(FabrykaObiektowGraficznychAbstrakcyjna * nowa_fabryka) { delete fabryka_;// usunięcie starej fabryki fabryka_=nowa_fabryka; // ustawienie nowej fabryki pobierzNowe(false);//żeby od razu zmienić typ przechowywanych obiektów } // dla rysowania obiektów void rysujObiekty(){ for (int licznik=0; licznikrysujSie(); } } } // konstruktor KlasaUzytkowa (FabrykaObiektowGraficznychAbstrakcyjna *nowa_fabryka){ fabryka_=nowa_fabryka; } // destruktor ~KlasaUzytkowa(){ for (int licznik=0; licznik<5; ++licznik){ delete pulaObiektow_[licznik];// zwolnienie puli obiektów } delete fabryka_;// zwolnienie fabryki } }; //Program testowy int main(){ cout<<"..:: Uruchamianie programu w trybie wysokiej jakosci grafiki ::.."<pobierzNowe(true);// Ustawianie przykładowych obiektów cout<<"..:: Rysowanie przykladowych obiektow ::.."<rysujObiekty(); //{...} Tutaj okazało się, że niestety maszyna jest za wolna cout<<"..:: Niestety maszyna jest za wolna, przelaczanie w tryb niskiej jakosci::.."<ustawFabryke(new FabrykaObiektowGraficznychProstych()); cout<<"..:: Rysowanie przykladowych obiektow ::.."<rysujObiekty(); cout<<"..:: Koniec programu ::.."<