
享元(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));
}
}
結語
此模式作為享元的物件需要是自生成後就固定不變的,因為都是參考到同一個記憶體,所以如果享元的物件被修改,全部都會一起變動。
享元模式常結合代理模式,好處除了減少物件記憶體之外,也減少從伺服器載入圖片的過程。
以上為學習過程的問題紀錄
如果文章有誤,歡迎前輩留言請不吝指教。
發佈留言