設(shè)計模式[12]-享元模式-Flyweight

1. 從Integer說起

下面的例子中,num1 == num2這個表達(dá)式輸出的是true,num3 == num4這個表達(dá)式輸出的是false,如你所知,Integer將了-128~127之間Integer對象緩存起來了,這些數(shù)值較小的對象,使用的頻率較高,復(fù)用可以提高效率。

Integer num1 = 127;  
Integer num2 = 127;  
Integer num3 = 128;  
Integer num4 = 128;
//true  
System.out.println(num1 == num2);
//false  
System.out.println(num3 == num4);

Integer類內(nèi)部有一個IntegerCache靜態(tài)內(nèi)部類,緩存了-128~127之間Integer對象,便于我們復(fù)用

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // 最大值可以配置,默認(rèn)是127
        int h = 127;
        // 略去讀取配置最大值的代碼
        high = h;
        // 創(chuàng)建要被緩存起來的Integer對象
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

Integer還提供了valueOf(int i)方法,當(dāng)i處于-128~127之間時,總是返回被緩存的Integer對象,達(dá)到復(fù)用的目的。這個方法,和工廠模式中獲取產(chǎn)品的方法是相似的。

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

2. 享元模式簡介

享元模式(FlyWeight Pattern)是結(jié)構(gòu)性設(shè)計模式,關(guān)注點在實現(xiàn)對象的復(fù)用,即運用共享技術(shù)有效地支持大量細(xì)粒度的對象。中文“享元”是意譯,更貼近本設(shè)計模式的本意,所謂“元”,即是“細(xì)顆粒度的對象”;所謂“享”,即是復(fù)用。java的String、Integer類都使用了享元模式,常用的場景還有線程池、數(shù)據(jù)庫連接池等。

享元模式一共有三種角色。

  • 抽象享元(Flyweight)角色 :給出一個抽象接口,以規(guī)定出所有具體享元角色需要實現(xiàn)的方法。這些方法可以向外界提供享元對象的內(nèi)部數(shù)據(jù)(內(nèi)蘊(yùn)狀態(tài)),同時也可以通過這些方法來設(shè)置外部數(shù)據(jù)(外蘊(yùn)狀態(tài))。

  • 具體享元類(ConcreteFlyweight):具體的享元對象,實現(xiàn)抽象享元接口。在具體享元類中為內(nèi)部狀態(tài)提供了存儲空間。通常我們可以結(jié)合單例模式來設(shè)計具體享元類,為每一個具體享元類提供唯一的享元對象。

  • 享元工廠(FlyWeight Factory): 主要用來創(chuàng)建并管理共享的享元對象,并對外提供訪問共享享元的接口。

Paste_Image.png
/**
 * 抽象享元角色
 */
public interface Flyweight {
    // 參數(shù)state是外蘊(yùn)狀態(tài)
    public void operate(String state);
}


/**
 * 具體享元角色
 */
public class ConcreteFlyweight implements Flyweight {
    /**內(nèi)部的狀態(tài)*/
    private String internalState;

    public ConcreteFlyweight(String internalState) {
        this.internalState = internalState;
    }

    /**
     * 一個示意性的方法,可以對內(nèi)蘊(yùn)狀態(tài)(數(shù)據(jù))和外蘊(yùn)狀態(tài)(數(shù)據(jù))做操作。
     * 
     * @param externalState 外部狀態(tài)
     */
    @Override
    public void operate(String externalState) {
        System.out.println("內(nèi)蘊(yùn)狀態(tài):" + internalState);
        System.out.println("外蘊(yùn)狀態(tài):" + externalState);
    }
}

/**
 * 享元工廠角色
 */
public class FlyweightFactory {

    //定義一個HashMap用于存儲享元對象,實現(xiàn)享元池
    private Map<String, Flyweight> flyweights = new HashMap<String, Flyweight>();

    public Flyweight getFlyweight(String key) {
        //如果對象存在,則直接從享元池獲取。
        if (flyweights.containsKey(key)) {
            return (Flyweight) flyweights.get(key);
        } else { //如果對象不存在,則創(chuàng)建一個新的對象,并添加到享元池中,然后返回。
            Flyweight flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
            return flyweight;
        }
    }
}

3. 題外話

跑個題,下表是國際職業(yè)拳擊聯(lián)盟對拳手17個級別的劃分,可見叫“FlyWeight”級別的拳手要求體重小于52.16千克,對于一個成年人來說,這樣的體重實在太輕了,是“細(xì)顆粒度”的。我們猜測,把此模式成為FlyWeight,是因為要復(fù)用的對象是細(xì)顆粒度的緣故。

序號 級別 劃分依據(jù) 級別英文名
1 草量級(迷你輕量級) 47.627kg以下(105磅) Minimumweight
2 次蠅量級(特輕量級) 不到48.980kg(108磅) Light Flyweight
3 蠅量級(次最輕量級) 不到50.800kg(112磅) Flyweight
4 次雛量級(超次最輕量級) 不到52.160kg(115磅) Super Flyweight
5 雛量級(最輕量級) 不到53.520kg(118磅) Bantamweight
6 次羽量級 不到55.340kg(122磅) Super Bantamweight
7 羽量級 不到57.150kg(126磅) Featherweight
8 次輕量級 不到58.970kg(130磅) Super Featherweight
9 輕量級 不到61.230kg(135磅) Lightweight
10 超輕量級 不到63.504kg(140磅) Light Welterweight
11 次中量級 不到66.680kg(147磅) Welterweight
12 超次中量級 不到69.850kg(154磅) Light Middleweight
13 中量級 不到72.570kg(160磅) Middleweight
14 超中量級 不到76.204kg(168磅) Super Middleweight
15 輕重量級 不到79.380kg(175磅) Light Heavyweight
16 次重量級 不到86.180kg(190磅) Cruiserweight
17 重量級 86.180kg以上(190磅以上) Heavyweight

(完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容