享元模式

享元工厂类(FlyweightFactoiy)角色:负责创建和管理享元对象。当一个客户端对象请求一个享元对象的时候,享元工厂需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。

抽象享元类(Flyweight)角色:它是所有具体享元类的超类。为这些类规定出需要实现的公共接口,那些需要外部状态的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。

具体享元类(ConcreteFlyweight)角色:具体享元类实现了抽象享元类所规定的接口。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元类又称为单纯具体享元类,因为复合享元类是由单纯具体享元角色通过复合而成的。

不能共享的具体享元类(UnsharableFlyweight)角色:不能共享的享元类,又叫做复合享元类。一个复合享元对象是由多个单享元对象组成,这些组成的对象是可以共享的,但是复合享元类本身并不能共享。

客户类(Client):客户类需要自行存储所有享元对象的外部状态。

使用环境:

当以下所有的条件都满足时,可以考虑使用享元模式:

  • 一个系统有大量的对象。
  • 这些对象耗费大量的内存。
  • 这些对象的状态中的大部分都可以外部化
  • 这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除时,每一个组都可以仅用一个对象代替。
  • 软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。

 

//Flyweight
class Character  
{
public:
    virtual ~Character(){};
    virtual void SetSize(int, int) = 0;
    virtual void Display() = 0;
protected:
    Character(){};
    char m_chSymbol;
    int m_nWeight;
    int m_nHeight;
};
//ConcreteFlyweight
class CharacterA : public Character
{
public:
    CharacterA();
    virtual ~CharacterA();
    void SetSize(int, int);//外部状态
    void Display();
};
CharacterA::CharacterA()//内部状态
{
    this->m_chSymbol = 'A';
    this->m_nWeight = 100;
    this->m_nHeight = 200;
}
CharacterA::~CharacterA()
{
}
void CharacterA::SetSize(int nWeight, int nHeight)
{
    this->m_nWeight = nWeight;
    this->m_nHeight = nHeight;
}
void CharacterA::Display()
{
    cout << "CharacterA:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
}

class CharacterB : public Character
{
。。。。。。。
};

//FlyweightFactory
class CharacterFactory  
{
public:
    CharacterFactory();
    virtual ~CharacterFactory();
    Character* GetCharacter(char);
private:
    std::map<char, Character*> m_mChar;
};
CharacterFactory::CharacterFactory()
{
    m_mChar.insert(make_pair<char, Character*>('A', new CharacterA));  
    m_mChar.insert(make_pair<char, Character*>('B', new CharacterB));  

}
CharacterFactory::~CharacterFactory()
{
}
Character* CharacterFactory::GetCharacter(char chIn)
{
    map<char, Character*>::iterator it = m_mChar.find(chIn);
    if(it != m_mChar.end())
    {
          return (Character*)it->second;
    }
     return NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
    CharacterFactory* pFactory = new CharacterFactory;

    //内蕴状态 存储在享元对象内部并且不会随环境改变而改变
   Character* ch1 = pFactory->GetCharacter('A');
   ch1->Display();

    //外蕴状态 客户端保存
    Character* ch2 = pFactory->GetCharacter('B');
     ch2->SetSize(500, 800);
     ch2->Display();
     return 0;
}

 

 

优点:

1.在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:

缺点:

1、享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。

2、享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。

个人感觉:

此模式运用: 经常使用对象,他们的属性是相同的,但是具体又有不同。比如文字:A-Z他们的有默认的一些参数。我们可以为一个个ConcreteFlyweight角色。我们用时就可能需要字号不同啦,颜色不同啦。这些属于外部状态啊。可以通过client去设置。

第二个缺点有待考究。

 

 

 

posted @ 2013-07-13 11:34  风啊  阅读(160)  评论(0)    收藏  举报