學習設計模式系列之六:享元模式

享元模式:ios

  在設計實現包含大量對象的數據結構時,考慮將對象劃分爲可共享的部分和不可共享的部分,其中可共享的部分共享存儲,不可共享的部分單獨存儲,從而節約存儲空間。數據結構

核心實現:函數

  共享重複的數據。大數據

  使用hash_table、set等集合,有效的管理動畫

  本質上是一種壓縮,是一種處理大數據的方式。spa

適用場景:設計

  對象個數極多code

  對象之間的重複屬性特別多對象

  經常使用於富格式文本的存儲blog

舉例說明:

  一個地圖中,有不少不少用於裝飾的植物,如花朵、草叢、仙人掌等等,衆多的植物每個都是一個對象,每一個植物對象都有顏色、高度、座標、當前幀、動畫貼圖等等,其中動畫貼圖將佔據大量的內存空間。若是不使用享元模式,將會因爲大量的重複數據而形成浪費,以下圖:

 

圖 1 非享元模式

  而使用享元模式,則能夠有效的管理重複內存,從而節約空間,以下圖:

 

圖 2 享元模式

代碼:

  1 #include <memory>
  2 #include <hash_map>
  3 #include <string>
  4 #include <iostream>
  5 
  6 /***
  7 * @author:zanzan101
  8 */
  9 
 10 using namespace std;
 11 
 12 // 模擬圖像數據的存儲結構
 13 class ImageData
 14 {
 15 private:
 16     char* _name;
 17     char _data[100];
 18 public:
 19     ImageData(const char* name):_name(0)
 20     {
 21         _name = 0;
 22         _name = new char[strlen(name)+1];
 23         strcpy(_name, name);
 24         memset(_data, 0, sizeof(_data));
 25     }
 26 
 27     static ImageData load_image(const char* name)
 28     {
 29         return ImageData(name);
 30     }
 31 
 32     bool operator==(const char* name) const
 33     {
 34         return string(_name) == string(name);
 35     }
 36 
 37     const char* get_image_name() const {return _name;}
 38 
 39 };
 40 
 41 class Plant
 42 {
 43 private:
 44     int _pos_x;
 45     int _pos_y;
 46     char* _image_name;
 47 public:
 48     Plant(const char* name):_pos_x(0), _pos_y(0), _image_name(0)
 49     {
 50         _image_name = new char[strlen(name)+1];
 51         strcpy(_image_name, name);
 52     }
 53     int get_pos_x(){return _pos_x;}
 54     int get_pos_y(){return _pos_y;}
 55     const char* get_image_name(){return _image_name;}
 56 };
 57 
 58 class Map
 59 {
 60 private:
 61     // 存儲「內部狀態」,即:不一樣對象能夠共享的數據,共性的數據
 62     vector<ImageData> _image_data;
 63 
 64     // 存儲「外部狀態」,即:與環境相關,不一樣對象不能共享的數據,有個性的數據
 65     vector<Plant> _plant;
 66 public:
 67     void add_plant(const char* name)
 68     {
 69         _plant.push_back(Plant(name));
 70         for(int i = 0; i < _image_data.size(); i++)
 71             if (_image_data[i] == name)
 72                 return;
 73         _image_data.push_back(ImageData::load_image(name));
 74     }
 75     void render_image(const ImageData& image_data, int pos_x, int pos_y)
 76     {
 77         // 繪製圖像
 78         // 注意:這裏的image_data是const類型的,調用的函數必須也是const的類型的
 79         cout<< "render a plant : " << image_data.get_image_name() <<endl;
 80     }
 81 
 82     // 繪製一棵植物,這裏綜合用到了共享數據和私有數據
 83     void render_plant(Plant& plant)
 84     {
 85         vector<ImageData>::iterator iter;
 86         for(iter = _image_data.begin(); iter != _image_data.end(); iter++)
 87             if(*iter == plant.get_image_name())
 88                 break;
 89         if(iter != _image_data.end())
 90             render_image(*iter, plant.get_pos_x(), plant.get_pos_y());
 91     }
 92 
 93     // 繪製全部的植物
 94     void render()
 95     {
 96         for(int i = 0; i < _plant.size(); i++)
 97             render_plant(_plant[i]);
 98     }
 99 
100     // 獲取當前的存儲對象的信息
101     void info()
102     {
103         cout<< "num of plants : "<< _plant.size() << endl;
104         cout<< "num of images : "<< _image_data.size() << endl;
105     }
106 };
107 
108 int _tmain(int argc, _TCHAR* argv[])
109 {    
110     Map m;
111 
112     // 添加大量植物對象
113     m.add_plant("草叢");
114     m.add_plant("草叢");
115     m.add_plant("草叢");
116     m.add_plant("草叢");
117     m.add_plant("仙人掌");
118     m.add_plant("仙人掌");
119     m.add_plant("仙人掌");
120     m.add_plant("草叢");
121     m.add_plant("草叢");
122     m.add_plant("草叢");
123     m.add_plant("花朵");
124     m.add_plant("花朵");
125 
126     // 訪問植物對象
127     m.render();
128 
129     // 輸出存儲信息
130     m.info();
131 
132     system("pause");
133     return 0;
134 }

輸出結果:

render a plant : 草叢
render a plant : 草叢
render a plant : 草叢
render a plant : 草叢
render a plant : 仙人掌
render a plant : 仙人掌
render a plant : 仙人掌
render a plant : 草叢
render a plant : 草叢
render a plant : 草叢
render a plant : 花朵
render a plant : 花朵
num of plants : 12
num of images : 3
請按任意鍵繼續. . .
相關文章
相關標籤/搜索