今天師父請假
在公司自立自強
然後主管為我上了堂有趣的產品課😊
我還在喜歡上班的階段好好珍惜😚
Flyweight is a structural design pattern that lets you fit more objects into the available amount of RAM by sharing common parts of state between multiple objects instead of keeping all of the data in each object.
--Refactoring Guru
享元模式是一種結構型設計模式, 它讓你在有限的記憶體內,透過共享多個物件所擁有的共同狀態,來載入更多物件;而不是在每個物件中保存所有資料。
這個設計模式基本上用於減少已創建的物件數量,降低記憶體的佔用,並提升應用程式的整體性能。
這代表著享元設計模式試圖通過將相似類型的已存在物件存儲在cache中,當找不到匹配的物件時再創建一個新的物件。
舉例來說~
我們在玩一些線上RPG遊戲時,每個玩家都可以創建自己的角色,
可以捏臉呀~ 放上人物特效呀~換裝等等。
但如果玩家人數眾多(幾千、甚至幾萬),如果每個玩家角色都為獨立物件,會耗費大量的記憶體。
用享元模式的邏輯,玩家角色物件可以分為外部狀態
(extrinsic state)以及內部狀態
(intrinsic state)
來緩解記憶體問題的解決方法是:
內部狀態
並共享給所有玩家。外部狀態
,存儲在各個玩家物件中。當玩家加入遊戲時,只需創建一個共享的角色外觀(例如,一個遊戲角色模型),
然後為每個玩家創建一個狀態對象,其中包含他們的特定數據。
這樣可以大大減少記憶體使用,因為大部分資源都是共享的,而不是為每個玩家都創建一個完整的角色物件~~~
來試著用遊戲角色創建,寫一個簡單的C#享元模式~~
假設今天這款遊戲有巫師
還有戰士
兩種角色模型,它們屬於 內部狀態
其餘特效、掛件、服裝等屬於 外部狀態
首先建立角色介面
// 抽象享元角色 (Interface)
abstract class Character
{
public abstract void Display(string playerName, string externalState);
}
具體享元角色
// 具體享元角色
class ConcreteCharacter : Character
{
private string model; // 內部狀態:角色模型
public ConcreteCharacter(string model)
{
this.model = model;
}
public override void Display(string playerName, string externalState)
{
Console.WriteLine($"Player: {playerName}, Model: {model}, {externalState}");
}
}
享元工廠~
// 享元工廠
class CharacterFactory
{
private Dictionary<string, Character> characters = new Dictionary<string, Character>();
public Character GetCharacter(string model)
{
if (!characters.ContainsKey(model))
{
characters[model] = new ConcreteCharacter(model);
}
return characters[model];
}
}
最後是客戶端程式碼~~
// 客戶端
class Client
{
static void Main()
{
CharacterFactory characterFactory = new CharacterFactory();
// 玩家加入遊戲,共享相同模型的角色外觀,並添加外部狀態
Character player1Character = characterFactory.GetCharacter("Warrior");
player1Character.Display("Player1", "Snowflake Effect, Sword, Cape");
Character player2Character = characterFactory.GetCharacter("Warrior");
player2Character.Display("Player2", "Fire Effect, Bow, Cloak");
// 更多玩家加入遊戲,共享相同模型的角色外觀,並添加外部狀態
Character player3Character = characterFactory.GetCharacter("Wizard");
player3Character.Display("Player3", "Lightning Effect, Staff, Robe");
Character player4Character = characterFactory.GetCharacter("Wizard");
player4Character.Display("Player4", "Ice Effect, Wand, Cloak");
}
}
output!