享元模式 Flyweight Pattern

来源:互联网 发布:ipad程序员必备app 编辑:程序博客网 时间:2024/05/29 11:43

享元模式 Flyweight Pattern

1.定义

享元模式,以共享的方式高效地支持大量的细粒度的对象。通过复用内存中已存在的对象,
降低系统创建对象实例的性能消耗。

2.使用场景:

  • 当系统中某个对象类型的实例较多的时候。
  • 由于使用了大量的对象,造成了很大的存储开销。
  • 对象的大多数状态都可变为外蕴状态。
  • 在系统设计中,对象实例进行分类后,发现真正有区别的分类很少的时候。

3.模式解析

图示:
这里写图片描述

  • 抽象享元类(Flyweight): 此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口或抽象类。那些需要外部状态(External State)的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
  • 具体享元类(ConcreteFlyweight):具体享元类实现了抽象享元类所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元类又称为单纯具体享元类,因为复合享元类是由单纯具体享元角色通过复合而成的。
  • 不能共享的具体享元类(UnsharableFlyweight):不能共享的享元类,又叫做复合享元类。一个复合享元对象是由多个单享元对象组成,这些组成的对象是可以共享的,但是复合享元类本身并不能共享
  • 享元工厂类(FlyweightFactoiy):享元工厂类负责创建和管理享元对象。当一个客户端对象请求一个享元对象的时候,享元工厂需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
  • 客户端(Client)角色:本角色还需要自行存储所有享元对象的外部状态。

4.总结:

享元模式是通过共享有效支持大量细粒度的对象,来提供应用程序的性能,节省系统中重复创建对象实例的性能消耗

5.代码实例:

#pragma once#include <iostream>using namespace std;#include <map>class Character{protected:    char symbol;    int  width;    int  height;    int  ascent;    int  descent;    int  pointSize;public:    virtual void Display(int pointSize) = 0;};class CharacterA : public Character{public:    CharacterA()    {        symbol = 'A';        height = 100;        width = 120;        ascent = 70;        descent = 0;    }    void Display(int _pointSize)    {        pointSize = _pointSize;        cout<<symbol<<" (pointsize "<< pointSize <<")"<<endl;    }};class CharacterB : public Character{public:    CharacterB()    {        symbol = 'B';        height = 100;        width = 140;        ascent = 72;        descent = 0;    }    void Display(int _pointSize)    {        pointSize = _pointSize;        cout<<symbol<<" (pointsize "<< pointSize <<")"<<endl;    }};class CharacterZ : public Character{public:    CharacterZ()    {        symbol = 'Z';        height = 100;        width = 100;        ascent = 68;        descent = 0;    }    void Display(int _pointSize)    {        pointSize = _pointSize;        cout<<symbol<<" (pointsize "<< pointSize <<")"<<endl;    }};/*    享元工厂类*/class CharacterFactory{public:    // 客户端通过这个函数请求享元对象    Character* GetCharacter(char key)    {        Character* character = nullptr;        map<char,Character*>::iterator it = _characters.find(key);        if( it != _characters.end() )        {            character =  it->second ;        }        else        { //没找到            switch (key)            {            case 'A':                character = new CharacterA();                break;            case 'B':                character = new CharacterB();                break;            case 'Z':                character = new CharacterZ();                break;            default:                break;            }            _characters.insert(make_pair(key,character));        }        return character;    }private:    map<char,Character*> _characters;};class FlyweightPatternExample1{public:    void Start()    {         string document = "AAZZBBZB";         CharacterFactory *factory = new CharacterFactory();         int pointSize = 10;         for( int i = 0 ; i < document.size();i++ )         {             pointSize++;             Character* character =  factory->GetCharacter(document[i]);             character->Display(pointSize);         }    }};

实验结果:
这里写图片描述

原创粉丝点击