【设计模式】——享元模式

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

相关文章
相关标签/搜索