首頁 » 設計模式 » 享元(Flyweight)

享元(Flyweight)

作者:

分類:

享元(Flyweight)

概念

享元模式是一種結構型模式,常用在固定且會大量生成的物件上,為了減少重複生成相同的物件造成記憶體浪費,享元模式會提供一個物件工廠,在需要物件時先檢查工廠內有沒有重複的物件,有就直接提供給使用者,否則生成後再提供。

想到之前有陣子很瘋的寶可夢地圖,在網頁上會顯示目前地圖上有哪些寶可夢出現,當相同的寶可夢大量出生時,會有很多相同的圖片同時顯示,這時就可以用到享元模式。

範例

//**************
//* author: cian
//* 20231029
//**************

/* 享元模式+代理模式範例 */
/* 寶可夢圖片的享元物件 */
class Pokemon
{
    private Image pokemonImg;
    public Pokemon(int pokemonID)
    {
        Console.WriteLine($"Load Pokemon image, ID:{pokemonID}.");
        pokemonImg = LoadPokemonImageFromServer();
    }
    
    public Image GetPokemonImage() { return pokemonImg; }
}

/* 享元工廠 */
class PokemonFactory
{
    private var pokemonDict = new Dictionary<int, Pokemon>();
    public Pokemon GetPokemon(int pokemonID)
    {
    	if (pokemonDict.ContainsKey(pokemonID)) {
            Console.WriteLine($"Return exists pokemon, ID:{pokemonID}.");
            return pokemonDict[pokemonID];
        } 
        else
        {
            var pokemon = new Pokemon(pokemonID);
            pokemonDict.Add(pokemonID, pokemon);
            return pokemon;
        }
    }
}

class MainApp
{
    static void Main(string[] args)
    {
        PokemonFactory factory = new PokemonFactory();
        PokemonMap map = new PokemonMap();
        
        /* Add pokemons on map*/
        /* 在地圖上生出3隻皮卡丘(id:25) */
        map.DrawPokemonOnMap(100, 200, factory.GetPokemon(25)); 
        map.DrawPokemonOnMap(200, 200, factory.GetPokemon(25)); 
        map.DrawPokemonOnMap(300, 200, factory.GetPokemon(25)); 
        
        /* 在地圖上生出2隻卡比獸(id:143) */
        map.DrawPokemonOnMap(100, 300, factory.GetPokemon(143)); 
        map.DrawPokemonOnMap(100, 500, factory.GetPokemon(143)); 
    }
}

結語

此模式作為享元的物件需要是自生成後就固定不變的,因為都是參考到同一個記憶體,所以如果享元的物件被修改,全部都會一起變動。

享元模式常結合代理模式,好處除了減少物件記憶體之外,也減少從伺服器載入圖片的過程。

以上為學習過程的問題紀錄
如果文章有誤,歡迎前輩留言請不吝指教。

「cian」的個人頭像

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *