使用VS + VS Code + Cocos2d-x写游戏
2026/4/25 7:19:18
通过共享大量细粒度对象的内在状态(不变部分),大幅减少内存占用,让成千上万个相似对象只占用少量内存。
游戏里渲染一片森林:
不共享:10万份完整模型 → 内存爆炸
享元模式:只存5份模型,所有树共享 → 内存节省99%!
不用享元,你会这样写:
structTree{Mesh mesh;// 每个树都完整复制一份网格(几MB)Texture texture;Vector3 position;floatscale;};// 10万棵树 = 几GB内存,寄!| 项目 | 装饰器(Decorator) | 组合(Composite) | 外观(Facade) | 享元(Flyweight) |
|---|---|---|---|---|
| 核心意图 | 动态叠加行为 | 部分-整体统一接口 | 简化复杂子系统 | 共享内在状态节省内存 |
| 关键机制 | 包装链 | 树形递归 | 统一入口 | 工厂 + 共享池 |
| 对象数量 | 少量 | 中等(树节点) | 单个外观 | 大量细粒度对象 |
| 典型场景 | 流加密/日志 | UI树/场景图 | 视频转码/编译器 | 游戏渲染、文字处理、粒子系统 |
| 口号 | “层层叠加” | “套娃统一” | “一键搞定” | “千树一面,共享内在” |
#include<iostream>#include<memory>#include<unordered_map>#include<vector>#include<string>usingnamespacestd;// 1. 享元接口(内在状态只读)classTreeModel{public:virtual~TreeModel()=default;virtualvoidrender(floatx,floaty,floatscale)const=0;virtualstringtype()const=0;};// 2. 具体享元(内在状态:网格、纹理等昂贵资源)classPineTree:publicTreeModel{public:voidrender(floatx,floaty,floatscale)constoverride{cout<<"[共享模型] 松树 @ ("<<x<<","<<y<<") 缩放:"<<scale<<endl;}stringtype()constoverride{return"Pine";}};classOakTree:publicTreeModel{public:voidrender(floatx,floaty,floatscale)constoverride{cout<<"[共享模型] 橡树 @ ("<<x<<","<<y<<") 缩放:"<<scale<<endl;}stringtype()constoverride{return"Oak";}};// 3. 享元工厂(核心:缓存共享对象)classTreeModelFactory{unordered_map<string,unique_ptr<TreeModel>>models;public:TreeModel*getModel(conststring&type){if(!models.count(type)){cout<<"[工厂] 创建新共享模型: "<<type<<endl;if(type=="Pine")models[type]=make_unique<PineTree>();elseif(type=="Oak")models[type]=make_unique<OakTree>();// 真实项目:这里加载网格、纹理等大资源,只加载一次!}returnmodels[type].get();// 返回共享指针}};// 4. 外在状态(每个树实例独有,轻量)structTreeInstance{floatx,y;floatscale;TreeModel*model;// 指向共享的享元voidrender()const{model->render(x,y,scale);}};intmain(){TreeModelFactory factory;vector<TreeInstance>forest;// 生成10万棵树,只创建2种共享模型for(inti=0;i<100000;++i){string type=(i%2==0)?"Pine":"Oak";forest.push_back({float(i%1000),float(i/1000),0.8f+(i%3)*0.2f,factory.getModel(type)});}cout<<"\n=== 开始渲染森林 ===\n";for(inti=0;i<10;++i){// 只渲染前10棵演示forest[i].render();}cout<<"... 剩余99990棵树同样共享模型,内存爆炸?不存在的!\n";}输出:
[工厂] 创建新共享模型: Pine [工厂] 创建新共享模型: Oak === 开始渲染森林 === [共享模型] 松树 @ (0,0) 缩放:0.8 [共享模型] 橡树 @ (1,0) 缩放:1 [共享模型] 松树 @ (2,0) 缩放:1.2 ...“千树万树同一模,内在共享外在独;
内存爆炸不存在,享元工厂真牛逼!”
当你面对“大量相似细粒度对象”(游戏实体、字符、粒子、图块),且内在状态远大于外在状态时,
立刻上享元模式——用工厂缓存共享对象,内存从GB降到MB!
现在,享元模式彻底说透了!
结构型模式还剩最后一篇:代理模式(Proxy)。