享元模式目的是为了减少对象实例化的个数,已达到减少对象占用内存的目的。他创建对象是通过工厂创建的,在工厂类中创建对象时,会先判断此对象是否已经存在,如果不存在则创建对象,如果存在则返回已经存在的对象,这是享元模式的核心部分。对于对象间的不同部分,则采用参数传递的方式将不同部分传进类的处理函数。
代码如下:
#include <iostream>
#include <string>
#include <map>
using namespace std;
class FlyWeight
{
public:
FlyWeight() {}
virtual void Operation (int extrinsicstate) = 0;
};
class ConcreteFlyWeight : public FlyWeight
{
public:
void Operation (int extrinsicstate)
{
cout << "ConcreteFlyWeight: " << extrinsicstate << endl;
}
};
class UnsharedConcreteFlyWeight :public FlyWeight
{
public:
void Operation (int extri)
{
cout << "UnsharedConcreteFlyWeight: " << extri << endl;
}
};
class FlyWeightFactory
{
public:
FlyWeightFactory ()
{
FlyWeight *f1 = new ConcreteFlyWeight ;
FlyWeight *f3 = new ConcreteFlyWeight ;
FlyWeight *f2 = new ConcreteFlyWeight ;
flyweights.insert (make_pair ("han", f1));
flyweights.insert (make_pair ("wang", f2));
flyweights.insert (make_pair ("zhang", f3));
}
FlyWeight* GetFlyWeight (string key)
{
return flyweights[key];
}
private:
map <string, FlyWeight *> flyweights;
};
class User
{
public:
User (string nm) : name (nm) {}
string GetName () { return name; }
private:
string name;
};
class WebSite
{
public:
virtual void Use (User *user) = 0;
};
class ConcreteWebSite : public WebSite
{
public:
ConcreteWebSite (string nm) : name (nm) {}
void Use (User *user)
{
cout << "ConcreteWebSite: " << name << "User: " << user->GetName()<< endl;
}
private:
string name;
};
class WebSiteFactory
{
public:
WebSite* GetWebSiteCategory (string key)
{
if (websites.find(key) == websites.end())
websites.insert(make_pair(key, new ConcreteWebSite(key)));
return websites[key];
}
int GetWebSiteCount ()
{
return websites.size();
}
private:
map <string, WebSite*> websites;
};
int main(void)
{
int extrinsicstate = 22;
FlyWeightFactory *f = new FlyWeightFactory ();
FlyWeight *fx = f->GetFlyWeight ("han");
fx->Operation (--extrinsicstate);
FlyWeight *fy = f->GetFlyWeight ("wang");
fy->Operation (--extrinsicstate);
FlyWeight *fz = f->GetFlyWeight ("zhang");
fz->Operation (--extrinsicstate);
UnsharedConcreteFlyWeight *uf = new UnsharedConcreteFlyWeight ();
uf->Operation (--extrinsicstate);
cout << "-----------------------" << endl;
WebSiteFactory *fw = new WebSiteFactory;
WebSite *fwn = fw->GetWebSiteCategory ("novel");
fwn->Use(new User ("hb"));
WebSite *fwb = fw->GetWebSiteCategory ("bolg");
fwb->Use(new User ("zt"));
cout << fwn << " " << fwb << endl;
WebSite *fwn2 = fw->GetWebSiteCategory ("novel");
cout << fwn2 << endl;
cout << fw->GetWebSiteCount () << endl;
char *p1 = "world";
char *p2 = "world";
cout << (const void*)p1 << " " << (const void*)p2 << endl;
return 0;
}
运行结果如下:
ConcreteFlyWeight: 21
ConcreteFlyWeight: 20
ConcreteFlyWeight: 19
UnsharedConcreteFlyWeight: 18
-----------------------
ConcreteWebSite: novelUser: hb
ConcreteWebSite: bolgUser: zt
0x9ff8f28 0x9ff8f98
0x9ff8f28
2
0x804c6d6 0x804c6d6
实现享元模式的核心在WebSiteFactory类,此类是一个对象工厂生成类,在生成一个对象时,它回去已经存在的对象集合websites中查找,若找到了则直接返回,若没有找到则new一个新对象并返回。
希望以后可以遇到用享元模式的场景,碰见别人写的代码运用此模式的也能够识别出来。
ps:代码最后两个相同的字符串char *p1 = "world";
打印出两个字符串的地址发现地址是一样的,这也是享元模式的一个应用。
char *p2 = "world";