设计模式之11 - 享元模式FlyWeight

本文介绍了享元模式的基本概念及其在减少内存中大量细粒度对象的应用。通过一个具体的字符绘制实例,展示了如何利用享元模式来提高系统性能,降低存储开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        享元模式 是结构性模式中一种非常有用的模式,其特点在于 复用内存中已存在的对象,从而降低创建对象的开销。

        这在系统中存在大量的 细粒度对象的情况下非常有用,比如 一篇英文文稿,里面的词成千上万,但是对应的英文字符只有26个,再加上10个数字,不考虑标点和其它特殊字符的情况下,只有36个对象。

        这就是 享元,共享的元素

        对于上面的例子,内存中只需要创建36个元素,这些元素在页面的绘制只是大小和位置不同。

        

        针对上面的word绘制实例,来看一段代码实现:

// 抽象字符类
class CharBase
{
public:
    // 绘制
    virtual void draw();

protected: // 属性
    char m_letter;
    int m_nFontSize;
};

// 具体字符类A
class CharA : public CharBase
{
    // 构造函数
    CharA()
    {
        this->m_letter= 'A';
        this->m_nFontSize= 12;
    }
    // 绘制
    virtual void draw()
    {
    }
};
// 具体字符类B
class CharB : public CharBase
{
    // 构造函数
    CharB()
    {
        this->m_letter= 'B';
        this->m_nFontSize= 12;
    }
    // 绘制
    virtual void draw()
    {
    }
};
        从面相对象的角度,这种方式看上去很合理,但实际上就产生了大量的内存对象,每个字符都要保存Font属性,并绘制一遍,在这里就变得极不合理。明智的做法是 从一个共享池中获取,也就是对应类图中的 FlyweightFactory(下面例子中的 CharFactory)。
class CharFactory
{
    // 构造函数
    CharFactory()
    {
        m_Chars[A] = new CharA();
        m_Chars[B] = new CharB();
    }
    // 获得指定字符实例
    CharBase* getChar(string& key)
    {
        map<string,CharBase*>::iterator ite = (CharBase*)m_Chars.find(key);
        if( ite == m_Chars.end() )
        {
            CharBase* pChar = NULL;
            if("A"==key)
                pChar = new CharA();
            else if("B"==key)
                pChar = new CharB();

            m_Chars[key] = pChar;
        }
        return pChar;
    }
protected:
    map<string,CharBase*> m_Chars;
};

       享元模式 需要将享元对象的状态外部化(上面例子中的FontSize),外部状态的读取会使得运行时间变长。

       享元模式 在一般的开发中并不常用,常常应用于系统底层的开发,以便解决系统的性能问题,以下情况成立时可以使用Flyweight模式。

1)一个应用程序使用了大量的对象。

2)由于使用大量的对象,造成很大的存储开销。

3)对象的大多数状态都可变为外部状态。

4)如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。

5)应用程序不依赖对象标识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值