享元模式(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