享元模式
定义
运用共享技术支持大量细粒度的对象。
结构
FlyWeight:抽象享元类,它定义了具体享元类实现的接口。
ConcreteFlyWeight:具体享元类, 为内部状态增加存储空间。
FlyWeightFactory:享元工厂类,核心是HashMap或者HashTable,工厂类初始化时将享元对象put到集合中,根据客户端提供的标识来返回指定的享元对象。
UnsharedConcreteFlyWeight:非共享的对象。
类图
享元工厂类:
public class FlyWeightFactory {
private Hashtable<String, FlyWeight> factory = new Hashtable<String, FlyWeight>();
public FlyWeightFactory(){
factory.put("X", new ConcreteFlyWeight());
factory.put("Y", new ConcreteFlyWeight());
factory.put("Z", new ConcreteFlyWeight());
}
public Hashtable<String, FlyWeight> getFactory() {
return factory;
}
public void setFactory(Hashtable<String, FlyWeight> factory) {
this.factory = factory;
}
}
抽象享元类:
public abstract class FlyWeight {
public abstract void operation(int n);
}
具体享元类:
public class ConcreteFlyWeight extends FlyWeight{
@Override
public void operation(int n) {
System.out.println("具体的flyWeight:"+n);
}
}
非共享对象:
public class UnsharedConcreteFlyWeight extends FlyWeight{
@Override
public void operation(int n) {
System.out.println("不共享的具体FlyWeight:"+n);
}
}
测试类
public static void main(String[] args) {
int n = 10;
FlyWeightFactory flyWeightFactory = new FlyWeightFactory();
FlyWeight flyWeight1 = flyWeightFactory.getFactory().get("X");
FlyWeight flyWeight2 = flyWeightFactory.getFactory().get("X");
FlyWeight flyWeight3 = flyWeightFactory.getFactory().get("X");
UnsharedConcreteFlyWeight unsharedConcreteFlyWeight = new UnsharedConcreteFlyWeight();
flyWeight1.operation(--n);
flyWeight2.operation(--n);
flyWeight3.operation(--n);
unsharedConcreteFlyWeight.operation(--n);
}
测试结果:
优点
大大减少重复对象的生成,减少了内存开销,提高性能。
缺点
增加系统的复杂度,外部状态随环境的改变而改变,而内部状态不会改变。
JDK类库中的享元模式
java.lang.Integer#valueOf(int)
java.lang.Boolean#valueOf(boolean)
java.lang.Byte#valueOf(byte)
java.lang.Character#valueOf(char)
java.lang.Long#valueOf(long)
我们都知道Integer有一个初始化值默认范围(-128到127),如果在这个范围内Integer.valueOf(n)这个方法返回缓存中的值,否则创建一个新的Integer对象。源码如下:
/**
* Returns a <tt>Integer</tt> instance representing the specified
* <tt>int</tt> value.
* If a new <tt>Integer</tt> instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Integer(int)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param i an <code>int</code> value.
* @return a <tt>Integer</tt> instance representing <tt>i</tt>.
* @since 1.5
*/
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Boolean类中初始化了两个静态常量TRUE、FALSE:
/**
* The <code>Boolean</code> object corresponding to the primitive
* value <code>true</code>.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The <code>Boolean</code> object corresponding to the primitive
* value <code>false</code>.
*/
public static final Boolean FALSE = new Boolean(false);
调用Boolean.valueOf(b)将会根据参数b返回实现缓存的常量。
Byte的valueOf方法和Integer同理,都是返回缓存中的值。
/**
* Returns a <tt>Byte</tt> instance representing the specified
* <tt>byte</tt> value.
* If a new <tt>Byte</tt> instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Byte(byte)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param b a byte value.
* @return a <tt>Byte</tt> instance representing <tt>b</tt>.
* @since 1.5
*/
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
Character值的默认范围是小于127,如果小于127,则返回缓存中的值,否则创建新的Character对象。
/**
* Returns a <tt>Character</tt> instance representing the specified
* <tt>char</tt> value.
* If a new <tt>Character</tt> instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Character(char)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param c a char value.
* @return a <tt>Character</tt> instance representing <tt>c</tt>.
* @since 1.5
*/
public static Character valueOf(char c) {
if(c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}