定义

享元(Flyweight)模式是指,运用共享技术有效地支持大量细粒度的对象。
 
结构
flyweight
 
理解
1.       Flyweight是享元抽象基类。Flyweight::Operation是公共接口,享元依赖的外部状态(ExtrinsicState)通过接口参数传入。
2.       ConcreteFlyweight具体享元类。具体享元必须是可共享的,必须为内部状态(IntrinsicState)提供存储空间。
3.       UnshareConcreteFlyweight是不可共享的具体享元,也叫做复合享元。复合享元是由单纯具体享元通过复合(Composite)模式而成的,将若干个具体享元作为子节点。
4.       FlyweightFactory是享元工厂。创建并管理享元对象。当Client请求一个享元对象时,FlyweightFactory返回一个已创建的享元对象(如果没有就先创建)。
5.       Client维护一个指向Flyweight的指针,并且存储Flyweight的外部状态。
 
要点
1.       一个应用程序使用了大量相同的对象。对于相同的对象只需要共享一份就可以了。如文本文档字符对象就会大量存在,如果不使用享元模式,就要使用大量的对象,将会耗费大量的存储开销。
2.       对于文本文档的字符对象,字符代码是内部状态,字体字号大小排版位置等是外部状态。对象的大多数状态都可变为外部状态。
3.       外部状态可以由一个单独的外部对象来存储。如文本文档,外部对象存储文档的排版信息。
 
应用
用文本文档来说明享元模式的应用。
源码中没有演示不可共享的具体享元。可通过引入行对象(Row),将Character作为Row的子节点来实现,Row就是不可共享的享元。
 
源码
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
 
//外部状态. 存放字体大小和位置
class CContext
{
public:
    CContext() : m_iIdx(0) {};
    void AppendFontSize(const int iFontSize)
    {
        m_vecFontSize.push_back(iFontSize);
    }
 
    int GetCharSize()
    {
        return m_vecFontSize[m_iIdx];
    }
    int GetCharIdx()
    {
        return m_iIdx;
    }
    void Next()
    {
        m_iIdx++;
    }
 
private:
    int m_iIdx;
    vector<int> m_vecFontSize;
};
 
//Flyweight
class CFlyweight
{
public:
    CFlyweight(){};
    virtual ~CFlyweight(){};
 
    //享元方法,context是外部状态,通过参数传入
    virtual void ShowInfo(CContext &context) = 0;
};
 
 
//ConcreteFlyweight
class CCharacter : public CFlyweight
{
public:
    CCharacter(const char c) : m_c(c) {};
    virtual void ShowInfo(CContext &context)
    {
        cout << "IntrinsicState: char=" << m_c << "; ExtrinsicState: index=" << context.GetCharIdx() << ", size=" << context.GetCharSize() << endl;
        context.Next();
    };
 
protected:
    char m_c; //内部状态
};
 
//FlyweightFactory. 可用单件模式. 不考虑释放资源
class CFlyweightFactory
{
public:
    CFlyweight* GetFlyweight(const char c)
    {
        map<char, CFlyweight*>::iterator itr = m_mapPool.find(c);
        if (itr != m_mapPool.end())
        {
            cout << c << " already exists." << endl;
            return itr->second;
        }
 
        cout << c << " added." << endl;
 
        CFlyweight* p = new CCharacter(c);
        m_mapPool[c] = p;
        return p;
    };
 
private:
    map<char, CFlyweight*> m_mapPool;
};
 
int main()
{
    CFlyweightFactory factory;
    CContext context;
    CFlyweight* p = NULL;
    p = factory.GetFlyweight(‘a’);
    context.AppendFontSize(8);
    p->ShowInfo(context);
 
    p = factory.GetFlyweight(‘b’);
    context.AppendFontSize(9);
    p->ShowInfo(context);
 
    p = factory.GetFlyweight(‘c’);
    context.AppendFontSize(10);
    p->ShowInfo(context);
 
    p = factory.GetFlyweight(‘b’);
    context.AppendFontSize(11);
    p->ShowInfo(context);
    return 0;
}
 
输出:
a added.
IntrinsicState: char=a; ExtrinsicState: index=0, size=8
b added.
IntrinsicState: char=b; ExtrinsicState: index=1, size=9
c added.
IntrinsicState: char=c; ExtrinsicState: index=2, size=10
b already exists.
IntrinsicState: char=b; ExtrinsicState: index=3, size=11
 

 

 


转载本站文章请注明,转载自:神秘果

本文链接: http://www.shenmiguo.com/archives/2009/311_design-patterns-flyweight.html

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <font color="" face="" size=""> <span style="">

*