定义:享元模式又称轻量级模式,是对象池的一种实现,类似于线程池,可以避免频繁的创建销毁对象,消耗性能。目的是共享对象资源,将多个对同一对象的访问集中起来。属于结构型模式。
应用场景:经常应用与系统底层开发,当有大量相似对象,或者相同对象需要频繁创建、销毁,需要用到缓冲池的场景。
享元模式一般和单例模式配合使用,将享元工厂声明为一个单例类来池化享元对象。
// 享元工厂:类似于线程池统一管理对象
public class FlyweightFactory {
private static Map pool = new HashMap();
public static IFlyweight getFlyweight(String key) {
if (!pool.containsKey(key)) {
IFlyweight flyweight = new ConcreteFlyweight(key);
pool.put(key, flyweight);
}
return pool.get(key);
}
}
源码中享元模式的应用
String常量池
jdk对String类型常量做了优化处理,相同内容的常量会指向同一块内存空间
public class FlyweightTest {
public static void main(String[] args) {
String s1 = "hello"; //常量
String s2 = "hello"; //常量
String s3 = "he" + "llo"; //编译阶段已经做了处理,等同于上面的常量
String s4 = new String("hello"); //创建了新的内存空间
String s5 = "he" + new String("llo"); //创建了新的内存空间
String s6 = s4.intern(); //取出内存中的常量值
String s7 = "he";
String s8 = "llo";
String s9 = s7 + s8; //编译阶段不会变量做优化处理
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s5); // false
System.out.println(s1 == s6); // true
System.out.println(s1 == s9); // false
System.out.println(s4 == s5); // false
System.out.println(s4 == s9); // false
System.out.println(s5 == s9); // false
}
}
Integer缓存池
jdk对Integer做了优化处理,经常使用的数字(-128 ~ 127之间)会缓存起来,直接从缓存池获取,不会重新创建
public class FlyweightTest {
public static void main(String[] args) {
Integer a = Integer.valueOf(100);
Integer b = Integer.valueOf(100);
Integer c = 100;
Integer d = Integer.valueOf(128);
Integer e = Integer.valueOf(128);
Integer f = 128;
System.out.println(a == b); //true
System.out.println(a == c); //true
System.out.println(d == e); //false
System.out.println(d == f); //false
}
}
介于-128到127之间的数字,会从缓存池中获取,否则会创建
public final class Integer extends Number implements Comparable{ 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]; } //.... } public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } }



