享元模式 Flyweight Pattern

享元模式 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);
         }
    }
};

實驗結果:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章