Skip to content

Head First 设计模式 18-蝇量模式

🏷️ 《Head First 设计模式》

又名 享元模式

如果想让一个类的一个实例能用来提供许多“虚拟实例”,就使用蝇量模式(Flyweight Pattern)。

书中以需要大量创建树对象的场景为例,如果采用带状态的树对象,需要耗费大量的内存。若改用虚拟树对象,可以显著的减少内存的消耗。

修改后的类图如下:

下图是两种模式在创建 1 亿 个树实例时的内存消耗对比。

上半部分的是使用 蝇量模式 的内存消耗,不到 400M;下半部分是未使用时的内存消耗,实例创建结束后维持在 2.4GB。对比还是很明显的。

优点

  • 减少运行时对象实例的个数,节省内存。
  • 将许多“虚拟”对象的状态集中管理。

用途和缺点

  • 当一个类有许多的实例,而这些实例能被同一方法控制的时候,我们就可以使用蝇量模式。
  • 蝇量模式的缺点在于,一旦你实现了它,那么单个的逻辑实例将无法拥有独立而不同的行为。

示例代码

Tree

不带状态的树模型。

csharp
class Tree
{
    public static void Display(int x, int y, int age)
    {
        //Console.WriteLine($"Display a {age} years old tree at ({x}, {y}).");
    }
}

TreeManager

虚拟树对象管理器。

csharp
class TreeManager
{
    const int LOOP_COUNT = 10000;
    int[,] trees = new int[LOOP_COUNT, LOOP_COUNT];

    public TreeManager()
    {
        var r = new Random();
        for (int i = 0; i < LOOP_COUNT; i++)
        {
            for (int j = 0; j < LOOP_COUNT; j++)
            {
                trees[i, j] = r.Next(1, LOOP_COUNT);
            }
        }
    }

    public void DisplayTrees()
    {
        for (int i = 0; i < LOOP_COUNT; i++)
        {
            for (int j = 0; j < LOOP_COUNT; j++)
            {
                Tree.Display(i, j, trees[i, j]);
            }
        }
    }
}

Client

客户端测试代码

csharp
var treeManager = new TreeManager();
treeManager.DisplayTrees();