您的位置:首页 > 其它

设计模式实现(二十二)--- 享元模式(Flyweight)

2014-08-13 13:19 459 查看
享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。



#include <iostream>
using namespace std;
//Flyweight类,它是所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
class Flyweight
{
public:
virtual void Operation(int extrinsicstate) = 0;
};

//ConcreteFlyweight是继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。
class ConcreteFlyweight : public Flyweight
{
public:
void Operation(int extrinsicstate)
{
cout << "具体Flyweight : " <<extrinsicstate<<endl;
}
};

//UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类。因Flyweight接口共享称为可能,但它并不强制共享
class UnsharedConcreteFlyweight : public Flyweight
{
public:
void Operation(int extrinsicstate)
{
cout << "不共享的具体Flyweight : " <<extrinsicstate<<endl;
}
};

//FlyweightFactory,是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。
class FlyweightFactory
{
private:
Flyweight *flyweights[3];
public:
FlyweightFactory()
{
//初始化工厂时,先生成三个实例
flyweights[0] = new ConcreteFlyweight[3];
flyweights[1] = new ConcreteFlyweight();
flyweights[2] = new ConcreteFlyweight();
}
~FlyweightFactory()
{
delete flyweights[0];
delete flyweights[1];
delete flyweights[2];
}
//根据客户请求,获得已生成的实例
Flyweight *GetFlyweight(int key)
{
if(key <= 2)
return flyweights[key];
else
return NULL;
}
};

int main()
{
int extrinsicstate = 22;

FlyweightFactory f;

Flyweight *f1 = f.GetFlyweight(0);
f1->Operation(--extrinsicstate);

Flyweight *f2 = f.GetFlyweight(1);
f2->Operation(--extrinsicstate);

Flyweight *f3 = f.GetFlyweight(2);
f3->Operation(--extrinsicstate);

Flyweight *uf = new UnsharedConcreteFlyweight();
uf->Operation(--extrinsicstate);

delete uf;
return 1;
}


FlyweightFactory可以在初始化的时候生成好对象,也可以在需要的时候再去判断对象是否为NULL来决定是否需要实例化。
之所以要UnshareConcreteFlyweight是因为在共享对象来降低内存损耗的同时,有时候我们是不希望共享的。该子类可以解决那些不需要共享对象的问题。
下面是一个实际的创建多个网站,采用享元模式的例子。对象时根据需要的时候才去实例化
#include <iostream>
#include <string>
#include <vector>
using namespace std;

//在需要的时候才分配的享元模式例子
//网站抽象类
class WebSite
{
public:
string name;
public:
WebSite(string name)
{
this->name = name;
}
virtual void Use() = 0;
};

//具体网站类
class ConcreteWebSite : public WebSite
{
public:
ConcreteWebSite(string name):WebSite(name)
{

}
void Use()
{
cout << "网站分类: " << name << endl;
}
};

//网站工厂类
class WebSiteFactory
{
private:
vector<WebSite *> flyweights;
public:
WebSite *GetWebSiteCategory(string index)
{
//在需要的时候才分配
vector<WebSite *>::iterator iter = flyweights.begin();
for(;iter != flyweights.end();iter++)
{
if(index == (*iter)->name)
{
return *iter;
}
}
WebSite *newAdd = new ConcreteWebSite(index);
flyweights.push_back(newAdd);
return newAdd;
}
//获得网站分类总数
int GetWebSiteCount()
{
return flyweights.size();
}
};

//客户端代码
int main()
{
WebSiteFactory f;

//实例化“产品展示”的“网站”对象
WebSite *fx = f.GetWebSiteCategory("产品展示");
fx->Use();

WebSite *fy = f.GetWebSiteCategory("产品展示");
fy->Use();

WebSite *fz = f.GetWebSiteCategory("产品展示");
fz->Use();

WebSite *fl = f.GetWebSiteCategory("博客");
fl->Use();

WebSite *fm = f.GetWebSiteCategory("博客");
fm->Use();

WebSite *fn = f.GetWebSiteCategory("博客");
fn->Use();

cout << "网站分类总数为 "<<f.GetWebSiteCount()<<endl;
return 1;

}
享元模式可以避免大量非常相似的开销。在程序设计中,有时候需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本都是相同的,有时就能够大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外边,在方法调用时将它们传递进来,就可以通过共享大幅度得减少单个实例的数目。
也就是说享元模式Flyweight执行时锁需的状态时有内部的也可能有外部的,内部状态存储于concreteFlyweight对象之中,而外部对象则应该考虑由客户端对象存储或计算,当调用Flyweight对象的操作时,将该状态传递给它。比如上面的例子,如果要加入客户的账号,那么就可以由专门的对象来处理。



#include <iostream>
#include <string>
#include <vector>
using namespace std;

//用户类,用于网站的客户账号,是“网站类的外部状态”
class User
{
public:
string name;
User(string name):name(name){}
};
//在需要的时候才分配的享元模式例子
//网站抽象类
class WebSite
{
public:
string name;
public:
WebSite(string name)
{
this->name = name;
}
virtual void Use(User &user) = 0;
};

//具体网站类
class ConcreteWebSite : public WebSite
{
public:
ConcreteWebSite(string name):WebSite(name)
{

}
void Use(User &user)
{
cout << "网站分类:" << name <<" 用户:"<<user.name<< endl;
}
};

//网站工厂类
class WebSiteFactory
{
private:
vector<WebSite *> flyweights;
public:
WebSite *GetWebSiteCategory(string index)
{
//在需要的时候才分配
vector<WebSite *>::iterator iter = flyweights.begin();
for(;iter != flyweights.end();iter++)
{
if(index == (*iter)->name)
{
return *iter;
}
}
WebSite *newAdd = new ConcreteWebSite(index);
flyweights.push_back(newAdd);
return newAdd;
}
//获得网站分类总数
size_t GetWebSiteCount()
{
return flyweights.size();
}
};

//客户端代码
int main()
{
WebSiteFactory f;
User user("");
//实例化“产品展示”的“网站”对象
user.name = "小菜";
WebSite *fx = f.GetWebSiteCategory("产品展示");
fx->Use(user);

user.name = "大鸟";
WebSite *fy = f.GetWebSiteCategory("产品展示");
fy->Use(user);

user.name = "娇娇";
WebSite *fz = f.GetWebSiteCategory("产品展示");
fz->Use(user);

user.name = "老顽童";
WebSite *fl = f.GetWebSiteCategory("博客");
fl->Use(user);

user.name = "乔峰";
WebSite *fm = f.GetWebSiteCategory("博客");
fm->Use(user);

user.name = "郭靖";
WebSite *fn = f.GetWebSiteCategory("博客");
fn->Use(user);

cout << "网站分类总数为 "<<f.GetWebSiteCount()<<endl;
return 1;

}

如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态。那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: