享元模式属于结构型模式。
定义:运用共享技术有效地支持大量细粒度的对象。
优点:减少单个实例的数目,来避免相似类的开销。
主要用于减少创建对象的数量,以减少内存的占用消耗和提高软件性能。
享元模式尝试重用现有的对象,如果没有找到,才会创建新的对象。
因为我们知道,对象是占据一定内存的,即使是一个空类,在c++中也占据1个字节的大小。
重复利用可以减少浪费,还能维护上一次的状态。
享元模式主要使用场景:
1、在设计之初,考虑到当系统中可能有很多对象的时候
2、这些对象还很占内存、操作重复
怎么使用:
一般会建立对应的关系表,维护已经创建的对象,通过创建对象时给他们的唯一标识,
从而通过标识从关系表中再次取出。
UML类图:
栗子场景:人在江湖飘,哪有不挨刀,加入一个门派接受保护成为了武林人士的首选。
其中Sects对应Flyweight,concreteSects对应concreateFlyweight,SectsFactory对应FlyweightFactory。
#include <iostream>
#include <map>
using namespace std;
//侠客类
class KnightErrant
{
public:
KnightErrant(string n) :m_name("")
{
m_name = n;
}
string getName()
{
return m_name;
}
private:
string m_name; //侠客的名字
};
//抽象门派
class Sects{
public:
virtual void JoinSects(KnightErrant ke) = 0;
};
//具体门派
class ConcreteSects:public Sects
{
public:
ConcreteSects(string n) :m_name("")
{
m_name = n;
}
void JoinSects(KnightErrant ke)
{
cout <<"大侠:"<< ke.getName().c_str()
<< " 加入" << m_name.c_str()<< endl;
}
private:
string m_name;
};
//享元工厂类
class SectsFactory
{
public:
~SectsFactory()
{
auto it = m_sectsMap.begin();
for (; it != m_sectsMap.end(); it++)
{
if (it->second)
{
delete it->second;
it->second = nullptr;
}
}
}
Sects* getSects(string name)
{
if (m_sectsMap.find(name) == m_sectsMap.end())
{
m_sectsMap[name] = new ConcreteSects(name);
}
return m_sectsMap[name];
}
int getSectsCount()
{
int cnt = 0;
auto it = m_sectsMap.begin();
for (; it != m_sectsMap.end(); it++)
{
cnt++;
}
return cnt;
}
private:
map<string, Sects*> m_sectsMap;
};
//客户端
int main()
{
SectsFactory *sectsFac = new SectsFactory;
Sects *sects = sectsFac->getSects("华山派");
sects->JoinSects(KnightErrant("令狐冲"));
sects->JoinSects(KnightErrant("任你行"));
sects = sectsFac->getSects("嵩山派");
sects->JoinSects(KnightErrant("鸠摩智"));
sects = sectsFac->getSects("峨眉派");
sects->JoinSects(KnightErrant("宋青书"));
cout << "当前武林门派的个数:" << sectsFac->getSectsCount() << endl;
if (sectsFac)
{
delete sectsFac;
sectsFac = nullptr;
}
return 0;
}
效果:
令狐冲和任你行都加入了华山派,鸠摩智和宋青书分别加入嵩山和峨眉。其中华山派已经已经存在,所以不会再new对象。