【结构型】享元模式

Posted by Liao on 2023-01-17

一、定义

运用共享技术有效地支持 大量细粒度对象 (如字符串、线程池)。

模式动机:软件系统采用纯粹对象方案的问题在于,大量细粒度对象会很快充斥在系统,从而带来很高的运行代价。(主要指内存需求方面的代价)

二、结构

基本思想(共享):

在共享池中查找对象是否创建过,如果对象创建过,则直接返回对象;否则先创建对象,把该对象放到共享池中。不过有些对象不支持恭共享。

三、使用场景

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
29
30
31
32
33
class Font { 
private:
// unique object key;
string key;
// object status;
// ...

public:
Font(const string& key) {

}
};


class FontFactory() {
private:
map<string, Font* > fontPool;

public:
Font* GetFont(const string& key) {
// 一般存储在共享池的对象状态不会改变,因此是只读状态。
map<string, Font*>::iterator item = fontPool.find(key);
if(item != fontPool.end()) { // 字体池中存在
return fontPool[key];
}
else { // 不存在则创建
Font* font = new Font(key);
fontPool[key] = font;
return font;
}
}
};

四、总结

  • 面向对象很好地解决了抽象性的问题,但作为运行在机器中的程序实体,我们要考虑对象的代价问题。Flyweight主要解决对象的代价问题,一般步涉及面向对象的抽象问题。
  • Flyweight采用对象共享的做法来降低系统中对象的个数(对象的大小需要合理评估),从而降低细粒度对象给系统带来的内存压力。在具体实现上,要注意对象的状态(只读)。
  • 对象的数量太大从而导致对象内存开销加大——此处的数量要实际应用情况评估,而不能凭空臆断。