在一些系统中,存在大量小粒度数据对象,这样带来很大的资源开销,如果这些对象存在可以共享的数据,可以通过多个对象共享数据,从而减少资源开销。例如游戏中的小怪,这些小怪的外观数据属于可共享数据,并不需要每个小怪的对象都保留外观数据。
Flyweight Pattern可以在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作。
类图:
Flyweight:共享数据对象接口
ConcreteFlyweight:共享对象实例
Flyweight:共享对象工厂
2. 实例
菜单上的菜有以下属性:名字、菜系、价格,其中菜系是可以作为共享数据share的。
代码:
#include <iostream>
#include <map>
#include <string>
using namespace std;
//Flyweight
class Flyweight
{
public:
virtual ~Flyweight()
{
}
virtual void print() = 0;
};
//ConcreteFlyWeight
class StyleCookingFlyweight : public Flyweight
{
public:
StyleCookingFlyweight(string s)
{
_name = s;
}
void print()
{
cout << "style: " << _name.c_str() << endl;
}
private:
string _name;
};
//FlyWeightFactory
class StyleCookingFlyweightFactory
{
public:
virtual ~StyleCookingFlyweightFactory()
{
map<string, Flyweight*>::iterator it;
for ( it = _style_cooking_map.begin(); it != _style_cooking_map.end(); it++ )
{
if((*it).second)
{
delete (*it).second;
(*it).second = NULL;
}
}
}
int get_size()
{
return _style_cooking_map.size();
}
Flyweight* get_style_cooking(string key)
{
Flyweight *flyweight;
map<string, Flyweight*>::iterator it;
it = _style_cooking_map.find(key);
// 存在则返回相应对象
if(it != _style_cooking_map.end() )
{
flyweight = (*it).second;
}
else// 否则插入新对象
{
flyweight = new StyleCookingFlyweight(key);
_style_cooking_map[key] = flyweight;
}
return flyweight;
}
private:
map<string, Flyweight*> _style_cooking_map;
};
//Object
class Food
{
public:
Food(const char* s, int price, Flyweight* style_flyweight)
{
_name = s;
_price = price;
_style_flyweight = style_flyweight;
}
void report()
{
cout << "name: " << _name << endl;
cout << "price: " << _price << endl;
_style_flyweight->print();
cout << endl;
}
private:
//共享数据
Flyweight* _style_flyweight;
//菜名
string _name;
//菜价
int _price;
};
//client
int main()
{
StyleCookingFlyweightFactory style_factory;
Food food1("Cold beef", 20, style_factory.get_style_cooking("Sichuan cuisine"));
Food food2("White oil belly", 15, style_factory.get_style_cooking("Sichuan cuisine"));
Food food3("Griddle skin beef", 30, style_factory.get_style_cooking("Hunan cuisine"));
food1.report();
food2.report();
food3.report();
cout << "Style Flyweight Factory size: " << style_factory.get_size() << endl;
return 0;
}
输出:
name: Cold beef
price: 20
style: Sichuan cuisine
name: White oil belly
price: 15
style: Sichuan cuisine
name: Griddle skin beef
price: 30
style: Hunan cuisine
Style Flyweight Factory size: 2