設計模式-享元模式(flyweight)以及在JDK類庫中的應用

享元模式

定義

運用共享技術支持大量細粒度的對象。

結構

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);
    }

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章