设计模式实现(二十二)--- 享元模式(Flyweight)
2014-08-13 13:19
459 查看
享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。
FlyweightFactory可以在初始化的时候生成好对象,也可以在需要的时候再去判断对象是否为NULL来决定是否需要实例化。
之所以要UnshareConcreteFlyweight是因为在共享对象来降低内存损耗的同时,有时候我们是不希望共享的。该子类可以解决那些不需要共享对象的问题。
下面是一个实际的创建多个网站,采用享元模式的例子。对象时根据需要的时候才去实例化
也就是说享元模式Flyweight执行时锁需的状态时有内部的也可能有外部的,内部状态存储于concreteFlyweight对象之中,而外部对象则应该考虑由客户端对象存储或计算,当调用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; }
如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态。那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式
相关文章推荐
- 学习php设计模式 php实现享元模式(flyweight)
- 设计模式学习笔记(二十二)—FlyWeight享元模式
- Java设计模式二十二:享元模式(Flyweight)
- 学习php设计模式 php实现享元模式(flyweight)
- 设计模式C++实现二十二:享元模式
- 设计模式十四(享元模式flyweight,python语言实现)
- Java设计模式二十二:享元模式(Flyweight)
- [GoF设计模式]Flyweight模式和State模式的C++实现
- 设计模式学习8 -- Flyweight(享元模式)
- 常见设计模式的解析和实现(C++)之十三-FlyWeight模式
- 设计模式—FlyWeight享元模式
- 重温设计模式(一)——享元模式(Flyweight)
- 设计模式学习笔记(十二)——Flyweight享元模式
- 设计模式--享元模式(Flyweight)
- 设计模式--Flyweight享元模式
- 设计模式--享元模式(Flyweight)
- 设计模式:享元模式Flyweight(转)
- 设计模式——享元模式(Flyweight)
- 设计模式循序渐进(4)享元模式 Flyweight
- 设计模式与泡mm的关系之flyweight享元模式及享元模式的再思考