享元模式
定義
運用共享技術支持大量細粒度的對象。
結構
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);
}