iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0

前言

今天師父請假
在公司自立自強/images/emoticon/emoticon33.gif
然後主管為我上了堂有趣的產品課😊
我還在喜歡上班的階段 好好珍惜😚

定義


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)
來緩解記憶體問題的解決方法是:

  • 共享相同的角色外觀和能力:遊戲中的某些元素是所有玩家共享的,例如相同的角色模型、動畫、音效、服飾等。這些可以被視為享元物件,只需創建一次內部狀態並共享給所有玩家。
  • 個別處理玩家特定的數據:每個玩家的特定數據,如位置、血量、裝備等,是不同的。這些數據可以被視為外部狀態,存儲在各個玩家物件中。

當玩家加入遊戲時,只需創建一個共享的角色外觀(例如,一個遊戲角色模型),
然後為每個玩家創建一個狀態對象,其中包含他們的特定數據。
這樣可以大大減少記憶體使用,因為大部分資源都是共享的,而不是為每個玩家都創建一個完整的角色物件~~~

UML


C#範例


來試著用遊戲角色創建,寫一個簡單的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!


上一篇
[Day16] Design Pattern - Facade 外觀模式
下一篇
[Day18] Design Pattern - Proxy代理模式
系列文
Design Pattern - 無所不在的設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言