享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。ios
#include <iostream> #include <vector> using namespace std; //Flyweight类,它是全部具体享元类的超类或接口,经过这个接口,Flyweight能够接受并做用于外部状态 class Flyweight { public: virtual void Operator(int extrinsicstate)=0; }; //ConcreteFlyweight是继承Flyweight超类或实现Flyweight接口,并为内部状态增长存储空间 class ConcreteFlyweight:public Flyweight { public: void Operator(int extrinsicstate) { cout << "具体Flyweight:" << extrinsicstate << endl; } }; //UnsharedConcreteFlyweight是指那些不须要共享的Flyweight子类。由于Flyweight接口共享成为可能,但他并不强制共享 class UnsharedConcreteFlyweight:public Flyweight { public: void Operator(int extrinsicstate) { cout << "不共享的具体Flyweight:" << extrinsicstate << endl; } }; //FlyweightFactory,是一个享元工厂,用来建立并管理Flyweight对象。它主要是用来确保合理的共享Flyweight, //当用于请求一个Flyweight时,FlyweightFactory对象提供一个已建立的实例或者建立一个(若是不存在的话) class FlyweightFactory { private: vector<Flyweight*> m_flyweights; public: FlyweightFactory() { Flyweight *temp=new ConcreteFlyweight(); m_flyweights.push_back(temp); } Flyweight *GetFlyweight(int key) { return m_flyweights.at(key); } }; int main() { int exetrinsicstate=22; FlyweightFactory *f=new FlyweightFactory(); Flyweight *fx=f->GetFlyweight(0); fx->Operator(exetrinsicstate); return 0; }
在享元对象内部而且不会随环境改变而改变的共享部分,能够成为是享元对象的内部状态,而随环境改变而改变的、不能够共享的状态就是外部状态了。事实上,享元模式能够避免大量很是类似的开销。在程序设计中,有时须要生成大量细粒度的类实例来表示数据。若是能发现这些实例除了几个参数外基本上都是相同的,有时就可以受大幅度地减小须要实例化的类的数量。若是能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就能够经过共享大幅度地减小单个实例的数目。也就是说,享元模式Flyweight执行时所需的状态是有内部的也可能有外部的,内部状态存储于ConcreteFlyweight对象之中,而外部对象则应该考虑由客户端对象存储或计算,当调用Flyweight对象的操做时,将该状态传递给它。性能
下面是关于网站分类的例子:网站
#include <iostream> #include <map> using namespace std; //用户类,用于网站的客户账号,是“网站”类的外部状态 class User { private: string m_name; public: User(string name) { this->m_name=name; } string GetName() { return m_name; } }; //网站抽象类 class WebSite { public: virtual void Use(User *user){} }; //具体网站类 class ConcreteWebSite:public WebSite { private: string m_name; public: ConcreteWebSite(string name) { this->m_name=name; } void Use(User *user) { cout << "网站分类:" << m_name << " 用户:" << user->GetName()<< endl; } }; //网站工厂类 class WebSiteFactory { private: map<string,WebSite*> m_flyweights; public: //得到网站分类 WebSite *GetWebSiteCategory(string key) { if(m_flyweights.find(key)==m_flyweights.end()) m_flyweights[key]=new ConcreteWebSite(key); return m_flyweights[key]; } }; int main() { WebSiteFactory *f=new WebSiteFactory(); WebSite *fx=f->GetWebSiteCategory("产品展现"); fx->Use(new User("小菜")); WebSite *fy=f->GetWebSiteCategory("产品展现"); fy->Use(new User("大鸟")); WebSite *f1=f->GetWebSiteCategory("博客"); f1->Use(new User("老顽童")); WebSite *fm=f->GetWebSiteCategory("博客"); fm->Use(new User("Awy")); return 0; }
若是一个应用程序使用了大量的对象,而大量的这些对象形成了很大的存储开销时,就应该考虑使用;还有就是对象的大多数状态能够是外部状态,若是删除对象的外部状态,那么能够用相对较少的共享对象取代不少组对象,此时能够考虑使用享元模式。由于用了享元模式,因此有了共享对象,实例总数就大大减小了,若是共享的对象越多,存储节约也就越多,节约量随着共享状态的增多而增大。this
在某些状况下,对象的数量可能会太多,从而致使了运行时的资源与性能损耗。那么咱们如何去避免大量细粒度的对象,同时又不影响客户程序,是一个值得去思考的问题,享元模式,能够运用共享技术有效地支持大量细粒度的对象。不过,你也别高兴得太早,使用享元模式须要维护一个记录了系统已有的全部享元的列表,而这自己须要耗费资源,另外享元模式使得系统更加复杂。为了使对象能够共享,须要将一些状态外部化,使得程序的逻辑发扎花。所以,应当在有足够多的对象实例可供共享时才值得使用享元模式。spa