Fork me on GitHub

设计模式———享元模式

享元模式:享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式。由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象。

介绍:运用共享技术有效地支持大量细粒度的对象。在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建

优点:大大减少对象的创建,降低系统的内存,使效率提高。

缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

应用案例:

1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。
2、数据库的数据池。

3、Integer的享元模式

使用场景:
1、系统有大量相似对象。
2、需要缓冲池的场景。

案例:

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
Integer i1 = 16 ;
Integer i2 = 16 ;
System.out.println(i1 == i2);

Integer i3 = 128 ;
Integer i4 = 128 ;
System.out.println(i3 == i4);
}
//结果 true false 也就是说当<128时,Integer对象都是共享的,当>=128时,才真正分配对象。

为什么i1和i2相等,而i3和i4不相等

分析源码:

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
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];

static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;

cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);

// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}

private IntegerCache() {}
}
1
2
3
4
5
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

从代码中可以看出,IntegerCache是Integer中的内部类,里面定义了两个属性,high,cache,其中high在static块中给出了赋值,如果配置integerCacheHighPropValue的话,默认的high是127,low=-128

如果i属于[-128,127],则返回cache[i+128],cache如代码所示,是IntegerCache的一个静态数组,是保存一份哦,因此,当自动装箱的i在[-128,127]范围内,则不生成新的Integer,而是共享了一个Integer对象。(享元模式),超出该范围的Integer才真正的new出了Integer对象。