享元模式(Flyweight Pattern)主要用于减少创建对象的数量,减少内存占用和提高性能。这种设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式尝试重用现有的类对象,如果未找到匹配的对象则创建新的对象。
意图
运用共享技术有效的支持大量细粒度的对象。
解决问题
在有大量对象时,有可能会造成栈溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回内存中已有的对象,避免重新创建对象。
如何解决
用唯一标识码判断,如果在内存中有,则返回这个唯一标示吗所标识的对象。
优点
大大减少对象的创建,减低 系统的内存,使效率更高。
缺点
提高了系统的复杂程度,需要分离外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部变化而变化,否则会造成系统的混乱。
使用场景
1.系统有大量相似的对象
2.需要缓冲池的场景
注意事项
1. 注意划分外部状态和内部状态,否则可能引起线程安全的问题
2. 这些类必须有一个工厂对象加以控制
享元模式结构图
C++实现
//享元模式
class Flyweight //抽象的享元类
{
public :
virtual void Operator(int i) = 0;
};
class ConcreteFlyweight : public Flyweight //共享的子类
{
public:
void Operator(int i)
{
cout <<"共享的Flyweight: " << i<<endl;
}
};
class UnshareConcreteFlyweight : public Flyweight
{
void Operation(int i)
{
cout << "不共享的Flyweight : " << i << endl;
}
};
class FlyweightFactory //享元工厂
{
private:
map<string, Flyweight*> flyweights; //模块名列表
public:
FlyweightFactory()
{
//这里需要用堆,因为这是给客户程序返回的,如果不用堆,则会返回局部对象的引用
flyweights["x"] = new ConcreteFlyweight();
flyweights["y"] = new ConcreteFlyweight();
flyweights["z"] = new ConcreteFlyweight();//所有的属性为“z”的模块都只对应这个一个实例,这正是享元模式的精髓所在呀
}
Flyweight* GetFlyWeight(string key)
{
if (!flyweights.count(key))
flyweights[key] = new ConcreteFlyweight();
return flyweights[key];
}
map<string, Flyweight*>::size_type CountN()//返回当前可共享的模块数
{
return flyweights.size();
}
};
客户端:
int test_Flyweight() //享元模式
{
int i = 100;
FlyweightFactory f;//整个过程采用一个工厂
Flyweight *px = f.GetFlyWeight("x");//获取x对应的模块
px->Operator(--i);
Flyweight* py = f.GetFlyWeight("y");
py->Operator(--i);
Flyweight* pz = f.GetFlyWeight("a");//a不在初始化的表中
pz->Operator(--i);
cout << "可共享的模块:"<<f.CountN() <<"个!" << endl;
delete px;
delete py;
delete pz;
px = py = pz = NULL;
system("pause");
return 0;
}