定义:运用共享技术有效地支持大量的细粒度的对象。
这个定义似乎有些抽象。我的理解就是在大量的对象中将那些重复出现,值相对稳定的属性集合抽象出来封装到共享对象从而减少重复对象的创建。
分类:结构型设计模式;
既然是可共享的状态,我觉得的很重要的一个特点就是不可变性,因为它被很多对象所引用,不可变性才能保证安全的使用(包括线程安全),Java中String(字符串常量池),Integer,Double等都是不可变的,它们也确实使用了享元模式来减少重复对象的创建。如果一个对象需要经常修改,可能就不适合使用享元模式了,因为它们并不能安全的共享,即使要共享可能也需要保证同步等额外的开销。
内部状态和外部状态:
另一种说法单纯享元模式和复杂享元模式。内部状态就是那些相对不可变的属性集合,外部状态就比如用户ID,这个属性就是随着用户的不同而不同,还有一些可变性的属性它们难以共享,这些属性就是外部状态。将内部属性和外部属性分离,共享内部属性正是享元模式的用武之地。
结构:
下面展示了享元模式基本的类图。
FlyWeightFactory:享元工厂,享元模式一般都和工厂模式结合起来使用,由工厂对象来控制享元对象的创建和缓存,如果可以确定哪些对象需要缓存,可以在类初始化的时候就创建好然后缓存起来;
FlyWeight:享元对象抽象;
ConcreteFlyWeight:具体的享元对象;
UnsharedConcreteFlyWeight:可能会有一些FlyWeight的子类,并不需要强制共享;
首先Integer类是一个final类,不可变类:
public final class Integer extends Number implements Comparable<Integer>
这是Integer中缓存实现:
(1)使用的静态成员类,这样的好处是可以延迟初始化;
(2)它只缓存了-127-128范围内;
(3)它也是在类初始化时就将享元对象准备好了;
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { ... cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); ... } private IntegerCache() {} }
下面是Integer的工厂方法,如果在缓存范围中就使用缓存的对象。
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }