Head First 设计模式 18-蝇量模式
又名 享元模式 。
如果想让一个类的一个实例能用来提供许多“虚拟实例”,就使用蝇量模式(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}).");
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
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]);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Client
客户端测试代码
csharp
var treeManager = new TreeManager();
treeManager.DisplayTrees();
1
2
2