• 设计模式 笔记 享元模式 Flyweight






    //---------------------------15/04/20----------------------------



    //Flyweight 享元模式------对象结构型模式

    /*

        1:意图:

            运用共享技术有效地支持大量细粒度的对象。

        2:动机:

        3:适用性:

            以下条件都成立时才能使用。

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

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

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

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

            5>应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于概念上明显有别的

              对象,标识测试将返回真值。

        4:结构:

            FlyweightFactory:

            flyweights--------------------------------->Flyweight:

            GetFlyweight(key)                           Operation(extrinsicState)

            { if(flyweight[key] exists)                     |

                return exisiting flyweight;                 |

              else                                          |

                create new flyweight;                       |

                add it to pool of flyweights;               |

                return the new flyweight;                   |

            }    |                               ------------------------

                 |                               |                      |

                 |                |---->ConcreteFlyweight        |--->UnsharedConcreteFlyweight

                Client------------|     Operation(extrinsicState)|    Operation(extrinsicState)

                                  |     instrinsicState          |    allState

                                  --------------------------------

        5:参与者:

            1>Flyweight

                描述一个接口,通过这个接口flyweight可以接受并作用于外部状态。

            2>ConcreteFlyweight

                实现Flyweight接口,并为内部状态(如果有的话)增加存储空间。ConcreteFlyweight对象必须是

                可共享的。它存储的内部状态必须和场景无关。

            3>UnsharedConcreteFlyweight

                并非所有的Flyweight子类都需要被共享。Flyweight接口使得共享成为可能,但是它并不强制共享。

                UnsharedConcreteFlyweight对象通常把ConcreteFlyweight对象作为子节点。

            4>FlyweightFactory

                1)创建并管理flyweight对象。

                2)确保合理地共享flyweight。拥有一个接口可以返回一个flyweight对象(如果不存在会创建一个)

            5>Client

                1)维持一个对flyweight的引用。

                2)计算或存储一个(或多个)flyweight的外部状态。

        6:协作:

            1>flyweight执行时所需的状态必定是内部的或外部的。内部状态存储于ConcreteFlyweight对象中;而

              外部对象则由Client对象存储或计算。当用户调用flyweight的操作时,只需要把状态传递给它。

              (就是operation的那个操作,可以传入一个状态,然后由ConcreteFlyweight对象实现操作)

            2>用户不应该直接对ConcreteFlyweight类进行实例化,而只能从FlyweightFactory对象得到

              ConcreteFlyweight对象。

              关于这点,可以直接隐藏掉ConcreteFlyweight的定义,只通过工厂返回基类指针。

        7:效果:

            1>这个模式使用时间来换空间(大量),因为参数传输,工厂查找,外部状态的计算都会产生运行时的开销。

            2>节省的空间由一下决定:

                1)因为共享而减少的 实例总数目。

                2)对象内部状态的 平均数目。

                3)外部状态时 计算的 还是存储的。

              总结起来:共享的Flyweight越多,节省越多。节省的量随着共享的状态(内部状态)的增多而增大。外部状态时

              计算的而非存储的。则能节省大量存储。

        8:实现:

            1>删除外部状态

                外部状态的数量和大小决定了Flyweight模式的可用性。如果外部状态很多而且存储要求高,那么删除

                外部状态就没有意义了。最理想的情况是:外部状态可以由一个单独的对象结构计算得到,且该结构的

                存储要求非常小。

            2>管理共享对象

                因为对象时共享的,所以用户不能直接对它进行实例化,通常FlyweightFactory可以帮助用户找到某个

                特定的Flyweight对象。FlyweightFactory通常采用关联存储(set map)帮助用户查找感兴趣的

                Flyweight对象。

        9:代码示例:                                                                             */


    //abstract Flyweight:声明了Flyweight的接口

    class Glyph

    {

    public:

        virtual ~Glyph();

        virtual void Draw(Window*, GlyphContext&);

        virtual void SetFont(Font*, GlyphContext&);

        virtual Font* GetFont(GlyphContext&);

        virtual void First(GlyphContext&);

        virtual void Next(GlyphContext&);

        virtual bool IsDone(GlyphContext&);

        virtual Glyph* Current(GlyphContext&);

        virtual void Insert(Glyph*,GlyphContext&);

        virtual void Remove(GlyphContext&);

        

    protected:

        Glyph();

    };


    //ConcreteFlyweight:这里只需要ascii码就够了

    class Character : public Glyph

    {

    public:

        Character(char);

        virtual void Draw(Window*, GlyphContext&);

        

    private:

        char _charcode;

    };


    //客户自己创建维护的 外部状态-字体

    //由于是根据范围来确定字体,所以字体采取btree来存储,btree的最底层对应了相应的字体。

    class GlyphContext

    {

    public:

        virtual ~GlyphContext();

        virtual void Next(int step = 1);

        virtual Font* GetFont();

        virtual void SetFont(Font*, int span = 1);

        

    private:

        int _index;

        BTree* _fonts;

    };


    //工厂,可以返回具体的Flyweight对象

    const int NCHARCODES = 128;


    class GlyphFactory

    {

    public:

        GlyphFactory();

        virtual ~GlyphFactory();

        virtual Character* CreateCharacter(char);

        virtual Row* CreateRow();

        virtual Column* CreateColumn();

        

    private:

        Character* _character[NCHARCODES];

    };



  • 相关阅读:
    Linux下的sleep()和sched_yield()(转)
    各种字符串Hash函数(转)
    linux 实时监控网速脚本(转)
    linux安装chrome及chromedriver(转)
    Couldn't open file /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 解决办法(转)
    linux 运行时限制CPU核数、内存、读写速度
    C语言函数sscanf()的用法-从字符串中读取与指定格式相符的数据(转)
    golang在线学习与编译网站
    电子书转换网站推荐
    入门级网站经典 w3cschool
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983130.html
Copyright © 2020-2023  润新知