【設計模式】——享元模式

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

相關文章
相關標籤/搜索