Wzorzec projektowy pyłek - flyweight

Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 3366 razy

Opis wzorca projektowego pyłek

Wzorzec projektowy pyłek należy do wzorców strukturalnych. Wzorzec ten umożliwia wydzielenie części wspólnej dla wielu obiektów i przechowywanie jej w jednym oddzielnym obiekcie, do którego obiekt główny odwołuje się poprzez wskaźnik. Ten wzorzec można wykorzystać w grze komputerowej, gdzie obiekty tej samej klasy mają przypisaną taką samą teksturę. Tekstury zawsze ważą sporo i zajmują sporo miejsca w pamięci więc aby zapobiec niepotrzebnemu ich powielaniu tworzy się specjalną klasę, gdzie przechowywane są obiekty tekstur. Dany obiekt w grze np. czołg określonego typu odwołuje się do znajdującego się pod wskazanym adresem obiektu tekstury. W ten sposób mogę utworzyć dowolną liczbę czołgów danego typu, dla których wykorzystywana będzie jedna i ta sama tekstura.

Przykładowy diagram UML wzorca projektowego pyłek

Poniższy diagram pokazuje zlepek wykorzystania trzech różnych wzorców projektowych:

Obiekt klasy Textures jest dostępny globalnie z poziomu metody statycznej getTextures i globalnie udostępnia możliwość dodawania nowych tekstur, które z kolei dodawane są przez obiekty klas M1A1_Abrams_tank i T34_tank.

Przykład diagramy UML wzorca projektowego pyłek
Rys. 1
Przykład diagramy UML wzorca projektowego pyłek, który wykorzystuje również wzorzec projektowy singleton oraz wzorzec projektowy metoda wytwórcza

Przykładowa implementacja wzorca projektowego pyłek w C++

#include <iostream> #include <string> #include <map> class Texture{ std::string texture; public: Texture(std::string path){ texture = "Texture created from: "; texture += path; std::cout << "Created new Texture from path: " << path << std::endl << std::endl; } void draw() const { std::cout << texture << std::endl << std::endl; } }; class Textures{ std::map<std::string, Texture*> textures; Textures(){ std::cout<<"Konstruktor textures"<<std::endl<<std::endl; } public: Texture* addTexture(std::string textureName, std::string texturePath){ std::map<std::string, Texture*>::iterator findTexture = textures.find(textureName); if(findTexture == textures.end()){ Texture* newTexture = new Texture(texturePath); this->textures[textureName] = newTexture; return newTexture; } std::cout << "Texture \apos" << textureName << "\apos already exist so I return existing texture!" << std::endl << std::endl; return findTexture->second; } Texture* getTexture(std::string textureName){ std::map<std::string, Texture*>::iterator findTexture = textures.find(textureName); if(findTexture == textures.end()){ return NULL; } return findTexture->second; } ~Textures(){ for(std::map<std::string, Texture* >::iterator texture = textures.begin(); texture != textures.end(); texture){ if(texture->second){ delete texture->second; texture->second = NULL; } } textures.clear(); } static Textures& getTextures() { static Textures textures; return textures; } }; class iTank{ protected: Texture* texture; std::string tankType; public: virtual void draw() const = 0; }; class M1A1_Abrams_tank : public iTank{ public: M1A1_Abrams_tank(){ tankType = "M1A1 Abrams"; texture = Textures::getTextures().addTexture("M1A1 Abrams tank", "tank_textures/M1A1_Abrams_tank.gif"); } virtual void draw() const { std::cout<<"Draw tank: " << tankType << std::endl << std::endl; if(texture){ texture->draw(); } } }; class T34_tank : public iTank{ public: T34_tank(){ tankType = "T34"; texture = Textures::getTextures().addTexture("T34 tank", "tank_textures/T34_tank.gif"); } virtual void draw() const { std::cout<<"Draw tank: " << tankType << std::endl << std::endl; if(texture){ texture->draw(); } } }; class TankFactory{ public: static iTank* createTank(std::string tankType){ if(tankType == "T34"){ return new T34_tank; } if(tankType == "M1A1 Abrams"){ return new M1A1_Abrams_tank; } return NULL; } }; int main(){ iTank* M1A1_Abrams_1 = TankFactory::createTank("M1A1 Abrams"); iTank* M1A1_Abrams_2 = TankFactory::createTank("M1A1 Abrams"); iTank* T34 = TankFactory::createTank("T34"); std::cin.get(); return 0; }

Wynik działania powyższego kodu:

Konstruktor textures

Created new Texture from path: tank_textures/M1A1_Abrams_tank.gif

Texture "M1A1 Abrams tank" already exist so I return existing texture!

Created new Texture from path: tank_textures/T34_tank.gif

Strony powiązane
strony powiązane
  1. sourcemaking.com/design_patterns/flyweight - strona opisująca wzorzec projektowy pyłek [En]
  2. pl.wikipedia.org - opis tego wzorca na stronie Wikipedii
Propozycje książek