现在的位置: 首页 > 综合 > 正文

flyweight pattern — 享元模式

2017年12月13日 ⁄ 综合 ⁄ 共 6974字 ⁄ 字号 评论关闭
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 -- 享元模式

抱歉!评论已关闭.