Wzorzec projektowy pyłek - flyweight

Stronę tą wyświetlono już: 94 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++

Listing 1
  1. #include <iostream>
  2. #include <string>
  3. #include <map>
  4. class Texture{
  5. std::string texture;
  6. public:
  7. Texture(std::string path){
  8. texture = "Texture created from: ";
  9. texture += path;
  10. std::cout << "Created new Texture from path: " << path << std::endl << std::endl;
  11. }
  12. void draw() const {
  13. std::cout << texture << std::endl << std::endl;
  14. }
  15. };
  16. class Textures{
  17. std::map<std::string, Texture*> textures;
  18. Textures(){
  19. std::cout<<"Konstruktor textures"<<std::endl<<std::endl;
  20. }
  21. public:
  22. Texture* addTexture(std::string textureName, std::string texturePath){
  23. std::map<std::string, Texture*>::iterator findTexture = textures.find(textureName);
  24. if(findTexture == textures.end()){
  25. Texture* newTexture = new Texture(texturePath);
  26. this->textures[textureName] = newTexture;
  27. return newTexture;
  28. }
  29. std::cout << "Texture \"" << textureName << "\" already exist so I return existing texture!" << std::endl << std::endl;
  30. return findTexture->second;
  31. }
  32. Texture* getTexture(std::string textureName){
  33. std::map<std::string, Texture*>::iterator findTexture = textures.find(textureName);
  34. if(findTexture == textures.end()){
  35. return NULL;
  36. }
  37. return findTexture->second;
  38. }
  39. ~Textures(){
  40. for(std::map<std::string, Texture* >::iterator texture = textures.begin(); texture != textures.end(); texture){
  41. if(texture->second){
  42. delete texture->second;
  43. texture->second = NULL;
  44. }
  45. }
  46. textures.clear();
  47. }
  48. static Textures& getTextures() {
  49. static Textures textures;
  50. return textures;
  51. }
  52. };
  53. class iTank{
  54. protected:
  55. Texture* texture;
  56. std::string tankType;
  57. public:
  58. virtual void draw() const = 0;
  59. };
  60. class M1A1_Abrams_tank : public iTank{
  61. public:
  62. M1A1_Abrams_tank(){
  63. tankType = "M1A1 Abrams";
  64. texture = Textures::getTextures().addTexture("M1A1 Abrams tank", "tank_textures/M1A1_Abrams_tank.gif");
  65. }
  66. virtual void draw() const {
  67. std::cout<<"Draw tank: " << tankType << std::endl << std::endl;
  68. if(texture){
  69. texture->draw();
  70. }
  71. }
  72. };
  73. class T34_tank : public iTank{
  74. public:
  75. T34_tank(){
  76. tankType = "T34";
  77. texture = Textures::getTextures().addTexture("T34 tank", "tank_textures/T34_tank.gif");
  78. }
  79. virtual void draw() const {
  80. std::cout<<"Draw tank: " << tankType << std::endl << std::endl;
  81. if(texture){
  82. texture->draw();
  83. }
  84. }
  85. };
  86. class TankFactory{
  87. public:
  88. static iTank* createTank(std::string tankType){
  89. if(tankType == "T34"){
  90. return new T34_tank;
  91. }
  92. if(tankType == "M1A1 Abrams"){
  93. return new M1A1_Abrams_tank;
  94. }
  95. return NULL;
  96. }
  97. };
  98. int main(){
  99. iTank* M1A1_Abrams_1 = TankFactory::createTank("M1A1 Abrams");
  100. iTank* M1A1_Abrams_2 = TankFactory::createTank("M1A1 Abrams");
  101. iTank* T34 = TankFactory::createTank("T34");
  102. std::cin.get();
  103. return 0;
  104. }

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

Komentarze