Różnice między wybraną wersją a wersją aktualną.
— |
fabryka_abstrakcyjna [2008/04/08 17:04] (aktualna) mchodkie utworzono |
||
---|---|---|---|
Linia 1: | Linia 1: | ||
+ | =====Abstract factory pattern (Fabryka abstrakcyjna)===== | ||
+ | <code cpp> | ||
+ | /************************************************************************************* | ||
+ | * 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 <iostream>//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: "<<x_<<", "<<y_<<endl; | ||
+ | } | ||
+ | ObiektGraficznyProsty (float x, float y):ObiektGraficznyAbstrakcyjny(x,y){} | ||
+ | }; | ||
+ | |||
+ | // Konkretny model obiektu graficznego, dla szybszych komputerów | ||
+ | class ObiektGraficznyTrudny : public ObiektGraficznyAbstrakcyjny { | ||
+ | public: | ||
+ | // funkcja rysujSie jest mocno okrojona, gdyż to tylko przykład zastosowania | ||
+ | void rysujSie(){ | ||
+ | cout<<"BARDZO WYMAGAJACY MODEL JEST RYSOWANY NA POZYCJI: "<<x_<<", "<<y_<<endl; | ||
+ | } | ||
+ | ObiektGraficznyTrudny (float x, float y):ObiektGraficznyAbstrakcyjny(x,y){} | ||
+ | }; | ||
+ | |||
+ | //Konkretna fabryka obiektów graficznych, dla wolnych komputerów | ||
+ | class FabrykaObiektowGraficznychProstych : public FabrykaObiektowGraficznychAbstrakcyjna { | ||
+ | public: | ||
+ | // skonkretyzowanie metody | ||
+ | ObiektGraficznyAbstrakcyjny * utworzObiekt(float x, float y) { | ||
+ | return new ObiektGraficznyProsty(x,y); | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | //Konkretna fabryka obiektów graficznych, dla szybkich komputerów | ||
+ | class FabrykaObiektowGraficznychTrudnych : public FabrykaObiektowGraficznychAbstrakcyjna { | ||
+ | public: | ||
+ | // skonkretyzowanie metody | ||
+ | ObiektGraficznyAbstrakcyjny * utworzObiekt(float x, float y) { | ||
+ | return new ObiektGraficznyTrudny(x,y); | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // Klasa korzystająca z fabryk | ||
+ | class KlasaUzytkowa { | ||
+ | private: | ||
+ | static const int ILE_OBIEKTOW=5;//ile obiektow graficznych naraz na ekranie maksymalnie | ||
+ | // Wskaznik na fabryke obiektow, tu bedzie podany wskaznik do konkretnej fabryki | ||
+ | FabrykaObiektowGraficznychAbstrakcyjna * fabryka_; | ||
+ | ObiektGraficznyAbstrakcyjny * pulaObiektow_[ILE_OBIEKTOW]; // Tablica obiektow do rysowania | ||
+ | public: | ||
+ | // dla zapełniania tablicy obiektów, zmienna nowa partia mówi czy zmieniać obiekty, | ||
+ | // czy też tworzyć nowe od poczatku | ||
+ | void pobierzNowe(bool nowaPartia){ | ||
+ | for (int licznik=0; licznik<5; ++licznik){ | ||
+ | ObiektGraficznyAbstrakcyjny * temp=pulaObiektow_[licznik]; | ||
+ | if (temp!=NULL){// odtworzenie obiektow w nowych warunkach | ||
+ | pulaObiektow_[licznik]=fabryka_->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; licznik<ILE_OBIEKTOW; ++licznik){ | ||
+ | if (pulaObiektow_[licznik]!=NULL){ | ||
+ | pulaObiektow_[licznik]->rysujSie(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | // 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 ::.."<<endl; | ||
+ | // Na początek ustawiany bardziej wymagający typ obiektu graficznego | ||
+ | KlasaUzytkowa * testowa=new KlasaUzytkowa(new FabrykaObiektowGraficznychTrudnych); | ||
+ | testowa->pobierzNowe(true);// Ustawianie przykładowych obiektów | ||
+ | cout<<"..:: Rysowanie przykladowych obiektow ::.."<<endl; | ||
+ | testowa->rysujObiekty(); | ||
+ | //{...} Tutaj okazało się, że niestety maszyna jest za wolna | ||
+ | cout<<"..:: Niestety maszyna jest za wolna, przelaczanie w tryb niskiej jakosci::.."<<endl; | ||
+ | testowa->ustawFabryke(new FabrykaObiektowGraficznychProstych()); | ||
+ | cout<<"..:: Rysowanie przykladowych obiektow ::.."<<endl; | ||
+ | testowa->rysujObiekty(); | ||
+ | cout<<"..:: Koniec programu ::.."<<endl; | ||
+ | } | ||
+ | </code> |