flyweight pattern 又称享元模式
Use sharing to support large numbers of fine-grained objects efficiently --- GoF
运用共享技术有效地支持大量细粒度的对象
UnshareConcreteFlyweight:
并不是所有的Flyweight具体实现子类都需要被共享的,如果是不能共享的,那么就只能是它只能被引用一个。
ConcreteFlyweight:
可以被共享,该对象可以被多个引用。
还是以汽车模型为例子,例如我们来建立一个跑车的部分场景,每个赛车都有轮胎,外壳,品牌,引擎
这个部分组成,轮胎影响飘逸和刹车的效果,外壳仅仅是外观效果,引擎影响最大速度和加速度,品牌影响可以被撞后影响。我们游戏会有40辆车,如果构建这20辆车需要160个对象,但是我们发现这160个对象太消耗系统性能与资源了,其实有些对象是一样的的,那么在这个场景中,完全可以共享这些对象,那么这样
可以节省好多对象的构造与析构,系统牺牲一定空间来提升性能与效率。
轮胎有:米其林,普利司通两种轮胎
Michelin轮胎:摩擦系数很高,漂移效果好,损耗很高
Bridgestone轮胎:摩擦细数一般,漂移效果一般,损耗一般
外壳有:红色,黑色,白色,蓝色,绿色,黄色,紫色七种
品牌有:宝马,法拉利,奥迪,奔驰四种
BMW:坚固性强,被撞减速一般
Ferrari: 坚固性弱,被减速大
Audi:坚固性一般,被减速大
Benz:坚固性一般,被减速小
引擎:法拉利研制,红牛研制,奔驰研制,宝马研制
Ferrari:速度高,加速高
Redbull:速度高,加速一般
Benz:速度一般,加速一般
BMW:速度一般,加速快
模拟从数据库或者配置表里获得数据
function.h文件
#include <iostream> float getFriction(std::string wheelname); float getDrifting(std::string wheelname); float getPorperty(std::string wheelname); int getPamer(std::string brandname); float getEffect(std::string brandname); int getMaxSpeed(std::string makename); int getAcceleration(std::string makename);function.cpp文件
#include "function.h" float getFriction(std::string wheelname) { if(wheelname=="Michelin")return 240; else if(wheelname=="Bridgestone")return 200; else return -1; } float getDrifting(std::string wheelname) { if(wheelname=="Michelin")return 100; else if(wheelname=="Bridgestone")return 80; else return -1; } float getPorperty(std::string wheelname) { if(wheelname=="Michelin")return 0.03; else if(wheelname=="Bridgestone")return 0.02; else return -1; } int getPamer(std::string brandname) { if(brandname=="BMW") return 3; else if(brandname=="Ferrari")return 1; else if(brandname=="Benz")return 2; else if(brandname=="Audi")return 2; else return -1; } float getEffect(std::string brandname) { if(brandname=="BMW")return 0.8; else if(brandname=="Ferrari") return 0.4; else if(brandname=="Benz")return 0.6; else if(brandname=="Audi")return 0.6; else return -1; } int getMaxSpeed(std::string makename) { if(makename=="BMW")return 400; else if(makename=="Benz")return 400; else if(makename=="Ferrari") return 500; else if(makename=="redBull") return 480; else return -1; } int getAcceleration(std::string makename) { if(makename=="BMW")return 9; else if(makename=="Ferrari")return 10; else if(makename=="Benz") return 8; else if(makename=="redBull")return 8; else return -1; }flyweight.cpp
#include <utility> #include <map> #include "function.h" class wheel { public: wheel(std::string n,float f,float d,float p) :name(n),friction(f),drifting(d),firstLoss(1), secondLoss(1),porperty(p) {} void run( ); void doDrifting( ); private: std::string name; float friction; float drifting; float firstLoss; float secondLoss; float porperty; }; void wheel::run() { firstLoss=firstLoss*(1-porperty); friction=friction*firstLoss; std::cout<<" Tire wear"<<std::endl; } void wheel::doDrifting() { secondLoss=secondLoss*(1-porperty); drifting=drifting*secondLoss; std::cout<<" car is drifting"<<std::endl; } class shell { public: shell(std::string c) :color(c) {} private: std::string color; }; class brand { public: brand(std::string n,int p,float e) :name(n),pamer(p),effect(e) {} int getPamer(){return pamer;} float getEffect(){return effect;} private: std::string name; int pamer; float effect; }; class engine { public: engine(std::string m,int s,int a) :made(m),maxSpeed(s),acceleration(a) {} int accelerate(int speed,int t); private: std::string made; int maxSpeed; int acceleration; }; int engine::accelerate(int speed,int t) { if(speed<maxSpeed) { for(int i=1;i<=t;++i) { speed=speed+acceleration; if(speed>maxSpeed) { speed=maxSpeed; break; } } } std::cout<<" car is accelerating"<<std::endl; return speed; } class car { public: car(std::string n,wheel *w,shell *s,brand *b,engine *e) :name(n),_wheel(w),_shell(s),_brand(b),_engine(e),speed(0) {} void run( ); void drifting(); void accelerate(int t); void collide(const car *c); void showSpeed(); std::string getName(); private: std::string name; wheel * _wheel; shell* _shell; brand* _brand; engine* _engine; float speed; }; std::string car::getName() { return name; } void car::run() { std::cout<<name; _wheel->run( ); } void car::drifting() { std::cout<<name; _wheel->doDrifting(); } void car::accelerate(int t) { std::cout<<name; speed=_engine->accelerate(speed,t); } void car::collide(const car* c) { if(_brand->getPamer()>=c->_brand->getPamer()) { std::cout<<name<<" car is stronger"<<std::endl; } speed=speed*c->_brand->getEffect( ); } void car::showSpeed() { std::cout<<name<<" car's speed is "<<speed<<std::endl; } class carFactory { public: car* getcar(std::string carname,std::string wheelname,std::string color,std::string brandname,std::string makename); ~carFactory(); private: std::map<std::string,wheel*> mw; std::map<std::string,shell*> ms; std::map<std::string,brand*> mb; std::map<std::string,engine*> me; }; car* carFactory::getcar(std::string carname,std::string wheelname, std::string color,std::string brandname,std::string makename) { wheel *w; std::map<std::string,wheel*>::iterator it1=mw.find(wheelname); if(it1==mw.end()) { float friction=getFriction(wheelname); float drifting=getDrifting(wheelname); float porperty=getPorperty(wheelname); w=new wheel(wheelname,friction,drifting,porperty); mw.insert(std::pair<std::string,wheel*>(wheelname,w)); } else { w=it1->second; } shell *s; std::map<std::string,shell*>::iterator it2=ms.find(color); if(it2==ms.end()) { s=new shell(color); ms.insert(std::pair<std::string,shell*>(color,s)); } else { s=it2->second; } brand *b; std::map<std::string,brand*>::iterator it3=mb.find(brandname); if(it3==mb.end()) { float effect=getEffect(brandname); float pamer=getPamer(brandname); b=new brand(brandname,pamer,effect); mb.insert(std::pair<std::string,brand*>(brandname,b)); } else { b=it3->second; } engine *e; std::map<std::string,engine*>::iterator it4=me.find(makename); if(it4==me.end()) { int maxSpeed=getMaxSpeed(makename); int acceleration=getAcceleration(makename); e=new engine(makename,maxSpeed,acceleration); me.insert(std::pair<std::string,engine*>(makename,e)); } else { e=it4->second; } return new car(carname,w,s,b,e); } carFactory::~carFactory() { for(std::map<std::string,wheel*>::iterator it1=mw.begin();it1!=mw.end();) { delete it1->second; mw.erase(it1++); } for(std::map<std::string,shell*>::iterator it2=ms.begin();it2!=ms.end();) { delete it2->second; ms.erase(it2++); } for(std::map<std::string,brand*>::iterator it3=mb.begin();it3!=mb.end();) { delete it3->second; mb.erase(it3++); } for(std::map<std::string,engine*>::iterator it4=me.begin();it4!=me.end();) { delete it4->second; me.erase(it4++); } } void collide(car* c1,car* c2) { std::cout<<c1->getName()<<" and "<<c2->getName()<<" are collide "<<std::endl; c1->collide(c2); c2->collide(c1); } int main(int argc,char** argv) { carFactory* c=new carFactory( ); car* c1=c->getcar("Han","Michelin","red","Ferrari","Ferrari"); car* c2=c->getcar("Bei","Bridgestone","white","BMW","BMW"); car* c3=c->getcar("Wu","Michelin","red","Benz","Ferrari"); c1->accelerate(40); c2->accelerate(40); c3->accelerate(40); c1->run(); c2->run(); c3->run(); c1->drifting(); c2->drifting(); c3->drifting(); c1->showSpeed(); c2->showSpeed(); c3->showSpeed(); collide(c1,c3); c1->showSpeed(); c2->showSpeed(); c3->showSpeed(); delete c; delete c1; delete c2; delete c3; return 0; }运行结果
如果有兴趣可以继续浏览该系列文章:
singleton pattern--单件模式factory mothed pattern--工厂方法模式abstract factory pattern--抽象工厂模式builder pattern--建造者模式prototype pattern--原型模式adapter pattern--适配器模式bridge pattern -- 桥接模式composite pattern -- 组合模式decorator pattern -- 装饰模式