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 -- 装饰模式
flyweight pattern -- 享元模式