享元模式: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 请按任意键继续. . .