网站建设中图片尺寸,福田网站(建设深圳信科),上海网页设计,做翻译网站 知乎设计模式[11]——享元模式一分钟彻底说清楚
一句话定义
通过共享大量细粒度对象的内在状态#xff08;不变部分#xff09;#xff0c;大幅减少内存占用#xff0c;让成千上万个相似对象只占用少量内存。
最狠的比喻#xff08;软件人专属#xff09;
游戏里渲染一片森林…设计模式[11]——享元模式一分钟彻底说清楚一句话定义通过共享大量细粒度对象的内在状态不变部分大幅减少内存占用让成千上万个相似对象只占用少量内存。最狠的比喻软件人专属游戏里渲染一片森林有10万棵树树只有5种模型松树、橡树、桦树、棕榈、樱花树每棵树的位置、大小、旋转角度不同外在状态但模型网格、纹理、材质完全相同内在状态不共享10万份完整模型 → 内存爆炸享元模式只存5份模型所有树共享 → 内存节省99%为什么需要它坏味道瞬间爆炸不用享元你会这样写structTree{Mesh mesh;// 每个树都完整复制一份网格几MBTexture texture;Vector3 position;floatscale;};// 10万棵树 几GB内存寄和之前模式彻底分清10秒表项目装饰器Decorator组合Composite外观Facade享元Flyweight核心意图动态叠加行为部分-整体统一接口简化复杂子系统共享内在状态节省内存关键机制包装链树形递归统一入口工厂 共享池对象数量少量中等树节点单个外观大量细粒度对象典型场景流加密/日志UI树/场景图视频转码/编译器游戏渲染、文字处理、粒子系统口号“层层叠加”“套娃统一”“一键搞定”“千树一面共享内在”真实软件例子游戏场景树渲染Unreal/Unity风格#includeiostream#includememory#includeunordered_map#includevector#includestringusingnamespacestd;// 1. 享元接口内在状态只读classTreeModel{public:virtual~TreeModel()default;virtualvoidrender(floatx,floaty,floatscale)const0;virtualstringtype()const0;};// 2. 具体享元内在状态网格、纹理等昂贵资源classPineTree:publicTreeModel{public:voidrender(floatx,floaty,floatscale)constoverride{cout[共享模型] 松树 (x,y) 缩放:scaleendl;}stringtype()constoverride{returnPine;}};classOakTree:publicTreeModel{public:voidrender(floatx,floaty,floatscale)constoverride{cout[共享模型] 橡树 (x,y) 缩放:scaleendl;}stringtype()constoverride{returnOak;}};// 3. 享元工厂核心缓存共享对象classTreeModelFactory{unordered_mapstring,unique_ptrTreeModelmodels;public:TreeModel*getModel(conststringtype){if(!models.count(type)){cout[工厂] 创建新共享模型: typeendl;if(typePine)models[type]make_uniquePineTree();elseif(typeOak)models[type]make_uniqueOakTree();// 真实项目这里加载网格、纹理等大资源只加载一次}returnmodels[type].get();// 返回共享指针}};// 4. 外在状态每个树实例独有轻量structTreeInstance{floatx,y;floatscale;TreeModel*model;// 指向共享的享元voidrender()const{model-render(x,y,scale);}};客户端10万棵树内存只占5个模型intmain(){TreeModelFactory factory;vectorTreeInstanceforest;// 生成10万棵树只创建2种共享模型for(inti0;i100000;i){string type(i%20)?Pine:Oak;forest.push_back({float(i%1000),float(i/1000),0.8f(i%3)*0.2f,factory.getModel(type)});}cout\n 开始渲染森林 \n;for(inti0;i10;i){// 只渲染前10棵演示forest[i].render();}cout... 剩余99990棵树同样共享模型内存爆炸不存在的\n;}输出[工厂] 创建新共享模型: Pine [工厂] 创建新共享模型: Oak 开始渲染森林 [共享模型] 松树 (0,0) 缩放:0.8 [共享模型] 橡树 (1,0) 缩放:1 [共享模型] 松树 (2,0) 缩放:1.2 ...C 真实项目里无处不在游戏引擎Unreal的Foliage系统、Unity的Instancing渲染共享Mesh和Material文字渲染每个字符A~Z只存一份Glyph字体轮廓成千上万文字实例共享粒子系统10万粒子共享几种粒子纹理和行为UI图标整个App共享一套图标纹理图集Texture AtlasQt/OpenGL共享VAO/VBO、Shader程序经典坑 正确姿势内在状态必须不可变共享对象不能被单个实例修改外在状态由客户端持有位置、颜色、缩放等享元工厂通常是单例或静态终极口诀游戏开发者专属“千树万树同一模内在共享外在独内存爆炸不存在享元工厂真牛逼”刻在DNA里的一句话当你面对“大量相似细粒度对象”游戏实体、字符、粒子、图块且内在状态远大于外在状态时立刻上享元模式——用工厂缓存共享对象内存从GB降到MB现在享元模式彻底说透了结构型模式还剩最后一篇代理模式Proxy。