後端開發 設計模式 · 第 12 / 24 篇

享元模式:節省記憶體的利器

享元模式 (Flyweight Pattern) 透過共享物件大幅節省記憶體資源。本文以 C# 樹木生成範例,教你如何有效管理大量重複物件。

哈囉各位朋友,今天我們要聊的是一個特別省資源的設計模式:享元模式(Flyweight)。

🌟 享元模式是什麼?

享元模式是一種可以有效節省記憶體的設計模式,透過共享相同或相似的物件,避免建立過多重複的小型物件。

舉個例子:假設你在做簡報,需要大量使用同一張圖片,與其在每張投影片裡都重新複製一次圖片,不如只保留一張原始圖片,其他投影片只需要參考這張圖片就好。這樣一來可以降低檔案大小,節省記憶體。


🤔 什麼情境適合使用享元模式?

  • 系統中存在大量重複的物件。
  • 物件的建立與銷毀成本過高,並且這些物件大多類似。
  • 想節省記憶體資源,提升系統效能。

🌳 C# 享元模式範例

以下以遊戲中常見的「樹木」為例,示範享元模式的實作方式。

🌳 享元介面與實作

using System;

/// <summary>
/// 樹木介面
/// </summary>
public interface ITree
{
    /// <summary>
    /// 顯示樹木
    /// </summary>
    /// <param name="x">位置 X 座標</param>
    /// <param name="y">位置 Y 座標</param>
    void Display(int x, int y);
}

/// <summary>
/// 具體享元類別
/// </summary>
public class Tree : ITree
{
    private readonly string _treeType;

    public Tree(string treeType)
    {
        _treeType = treeType;
        Console.WriteLine($"建立了一個 {treeType} 樹物件。");
    }

    /// <summary>
    /// 在指定位置顯示樹木
    /// </summary>
    public void Display(int x, int y)
    {
        Console.WriteLine($"在位置 ({x}, {y}) 顯示一棵{_treeType}樹。");
    }
}

🌲 享元工廠

using System.Collections.Generic;

/// <summary>
/// 享元工廠
/// </summary>
public class TreeFactory
{
    private readonly Dictionary<string, ITree> _trees = new Dictionary<string, ITree>();

    /// <summary>
    /// 取得樹木實例,若不存在則建立並快取
    /// </summary>
    public ITree GetTree(string treeType)
    {
        if (!_trees.ContainsKey(treeType))
        {
            _trees[treeType] = new Tree(treeType);
        }
        return _trees[treeType];
    }
}

🚀 實際使用範例

using System;

class Program
{
    static void Main(string[] args)
    {
        var treeFactory = new TreeFactory();

        // 建立多棵樹,但共用相同物件
        var oak = treeFactory.GetTree("橡樹");
        oak.Display(1, 1);
        oak.Display(2, 5);

        var maple = treeFactory.GetTree("楓樹");
        maple.Display(3, 3);
        maple.Display(4, 8);

        // 再次取得橡樹,會重複使用現有實例
        var anotherOak = treeFactory.GetTree("橡樹");
        anotherOak.Display(5, 5);
    }
}

🎯 執行結果

建立了一個 橡樹 樹物件。
在位置 (1, 1) 顯示一棵橡樹樹。
在位置 (2, 5) 顯示一棵橡樹樹。
建立了一個 楓樹 樹物件。
在位置 (3, 3) 顯示一棵楓樹樹。
在位置 (4, 8) 顯示一棵楓樹樹。

⚠️ 使用享元模式注意事項

  • 優點:有效減少記憶體消耗,尤其適用於大量重複物件的場景。
  • 缺點:程式碼結構相對複雜,需要謹慎管理共享物件生命週期。

🎉 結語

恭喜你,又成功掌握了享元模式(Flyweight)!學會這個模式,便能更有效率地管理資源,讓系統更輕盈高效。

持續關注我們的設計模式系列,學習更多實用又好玩的程式技巧吧!我們下篇見~

系列:

讀完了!你覺得這篇如何?

你的回饋會決定下一篇要寫什麼。

還有疑問

Learning path

設計模式

這篇是系列中的第 12 / 24 篇。可以順著列表補完整脈絡,也可以直接跳到需要的段落。

  1. 01 搞懂設計模式到底是什麼?
  2. 02 單例模式:只要一個就夠!
  3. 03 工廠方法模式:點披薩不用親自下廚
  4. 04 抽象工廠模式:系列產品輕鬆生產
  5. 05 原型模式:複製的藝術
  6. 06 建造者模式:一步步完成複雜任務
  7. 07 介面卡模式:讓不相容也能合作
  8. 08 橋接模式:抽象與實作分離
  9. 09 組合模式:樹狀結構的好幫手
  10. 10 裝飾者模式:讓功能自由加點
  11. 11 外觀模式:化繁為簡
  12. 12 享元模式:節省記憶體的利器 目前閱讀
  13. 13 代理模式:控制存取的守門員
  14. 14 責任鏈模式:層層把關的處理機制
  15. 15 命令模式:靈活封裝的請求指令
  16. 16 解譯器模式:讓程式聽懂你的指令
  17. 17 迭代器模式:輕鬆遍歷集合元素
  18. 18 中介者模式:管理複雜溝通的好幫手
  19. 19 備忘錄模式:保存與恢復物件狀態
  20. 20 觀察者模式:即時通知的好幫手
  21. 21 狀態模式:依狀態改變行為的祕訣
  22. 22 策略模式:靈活切換行為的好幫手
  23. 23 模板方法模式:固定流程靈活實作
  24. 24 訪問者模式:新增功能不動既有架構

Further reading

中介者模式:管理複雜溝通的好幫手 封面圖 2025-06-13 中介者模式:管理複雜溝通的好幫手 備忘錄模式:保存與恢復物件狀態 封面圖 2025-06-13 備忘錄模式:保存與恢復物件狀態 模板方法模式:固定流程靈活實作 封面圖 2025-06-13 模板方法模式:固定流程靈活實作

留言討論

用 GitHub 帳號留言,留言會同步到這個 Blog 的 GitHub Discussions。

閱讀導覽

約 3 分鐘

本篇所在系列 · 第 12 / 24 篇

設計模式

  1. 搞懂設計模式到底是什麼?
  2. 單例模式:只要一個就夠!
  3. 工廠方法模式:點披薩不用親自下廚
  4. 抽象工廠模式:系列產品輕鬆生產
  5. 原型模式:複製的藝術
  6. 建造者模式:一步步完成複雜任務
  7. 介面卡模式:讓不相容也能合作
  8. 橋接模式:抽象與實作分離
  9. 組合模式:樹狀結構的好幫手
  10. 裝飾者模式:讓功能自由加點
  11. 外觀模式:化繁為簡
  12. 享元模式:節省記憶體的利器
  13. 代理模式:控制存取的守門員
  14. 責任鏈模式:層層把關的處理機制
  15. 命令模式:靈活封裝的請求指令
  16. 解譯器模式:讓程式聽懂你的指令
  17. 迭代器模式:輕鬆遍歷集合元素
  18. 中介者模式:管理複雜溝通的好幫手
  19. 備忘錄模式:保存與恢復物件狀態
  20. 觀察者模式:即時通知的好幫手
  21. 狀態模式:依狀態改變行為的祕訣
  22. 策略模式:靈活切換行為的好幫手
  23. 模板方法模式:固定流程靈活實作
  24. 訪問者模式:新增功能不動既有架構
看完整系列 24 篇