夢幻之旅

          DEBUG - 天道酬勤

             :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            671 隨筆 :: 6 文章 :: 256 評論 :: 0 Trackbacks

          讓我們先來復(fù)習(xí)下javaString類型的特性:String類型的對象一旦被創(chuàng)造就不可改變;當(dāng)兩個String對象所包含的內(nèi)容相同的時候,JVM只創(chuàng)建一個String對象對應(yīng)這兩個不同的對象引用。讓我們來證實(shí)下著兩個特性吧(如果你已經(jīng)了解,請?zhí)^直接閱讀第二部分)。

          先來驗(yàn)證下第二個特性:

          public class TestPattern {

                 public static void main(String[] args){

                        String n = "I Love Java";

                        String m = "I Love Java";            

                        System.out.println(n==m);

                 }

          }

          這段代碼會告訴你n==mtrue,這就說明了在JVMnm兩個引用了同一個String對象(如果你還分不清== equals的區(qū)別的話,請先確認(rèn))。

          那么接著驗(yàn)證下第一個特性:

          在系統(tǒng)輸出之前加入一行代碼“m = m + "hehe";”,這時候n==m結(jié)果為false,為什么剛才兩個還是引用相同的對象,現(xiàn)在就不是了呢?原因就是在執(zhí)行后添加語句時,m指向了一個新創(chuàng)建的String對象,而不是修改引用的對象。

          呵呵,說著說著就差點(diǎn)跑了題,并不是每個String的特性都跟我們今天的主題有關(guān)的。
                String類型的設(shè)計(jì)避免了在創(chuàng)建N多的String對象時產(chǎn)生的不必要的資源損耗,可以說是享元模式應(yīng)用的范例,那么讓我們帶著對享元的一點(diǎn)模糊的認(rèn)識開始,來看看怎么在自己的程序中正確的使用享元模式!

          享元模式:運(yùn)用共享技術(shù)有效地支持大量大量細(xì)粒度的對象.

          享元模式英文稱為“Flyweight Pattern”,我非常感謝將Flyweight Pattern翻譯成享元模式的那位強(qiáng)人,因?yàn)檫@個詞將這個模式使用的方式明白得表示了出來;如果翻譯成為羽量級模式或者蠅量級模式等等,雖然可以含蓄的表現(xiàn)出使用此模式達(dá)到的目的,但是還是沒有抓住此模式的關(guān)鍵。

          享元模式的定義為:采用一個共享來避免大量擁有相同內(nèi)容對象的開銷。這種開銷中最常見、直觀的就是內(nèi)存的損耗。享元模式以共享的方式高效的支持大量的細(xì)粒度對象。

          在名字和定義中都體現(xiàn)出了共享這一個核心概念,那么怎么來實(shí)現(xiàn)共享呢?要知道每個事物都是不同的,但是又有一定的共性,如果只有完全相同的事物才能共享,那么享元模式可以說就是不可行的;因此我們應(yīng)該盡量將事物的共性共享,而又保留它的個性。為了做到這點(diǎn),享元模式中區(qū)分了內(nèi)蘊(yùn)狀態(tài)和外蘊(yùn)狀態(tài)。內(nèi)蘊(yùn)狀態(tài)就是共性,外蘊(yùn)狀態(tài)就是個性了。

          注:共享的對象必須是不可變的,不然一變則全變(如果有這種需求除外)。
             內(nèi)蘊(yùn)狀態(tài)
          存儲在享元內(nèi)部,不會隨環(huán)境的改變而有所不同,是可以共享的;外蘊(yùn)狀態(tài)是不可以共享的,它隨環(huán)境的改變而改變的,因此外蘊(yùn)狀態(tài)是由客戶端來保持(因?yàn)榄h(huán)境的變化是由客戶端引起的)。在每個具體的環(huán)境下,客戶端將外蘊(yùn)狀態(tài)傳遞給享元,從而創(chuàng)建不同的對象出來。至于怎樣來維護(hù)客戶端保持的外蘊(yùn)狀態(tài)和享元內(nèi)部保持的內(nèi)蘊(yùn)狀態(tài)的對應(yīng)關(guān)系,你先不用擔(dān)心這個問題,我們后面會涉及到的。

          我們引用《Java與模式》中的分類,將享元模式分為:單純享元模式和復(fù)合享元模式。在下一個小節(jié)里面我們將詳細(xì)的講解這兩種享元模式。



          享元模式的組成部份:
          1.享元接口 定義了享元
          2.具體享遠(yuǎn) 實(shí)現(xiàn)享元接口
          3.享元工廠 負(fù)責(zé)管理和創(chuàng)建享元對象,一般包含一個Map, 保存享元對象,使用都請求享元時,先到map里找是否有這個享元,如果有,返回,沒有就創(chuàng)建該享元.機(jī)制有點(diǎn)像對時所做的簡單的緩存.
          各部份的組成關(guān)系:



          使用優(yōu)缺點(diǎn)

          享元模式優(yōu)點(diǎn)就在于它能夠大幅度的降低內(nèi)存中對象的數(shù)量;而為了做到這一步也帶來了它的缺點(diǎn):它使得系統(tǒng)邏輯復(fù)雜化,而且在一定程度上外蘊(yùn)狀態(tài)影響了系統(tǒng)的速度。

          所以一定要切記使用享元模式的條件:

          1)        系統(tǒng)中有大量的對象,他們使系統(tǒng)的效率降低。

          2)        這些對象的狀態(tài)可以分離出所需要的內(nèi)外兩部分。

          外蘊(yùn)狀態(tài)和內(nèi)蘊(yùn)狀態(tài)的劃分以及兩者關(guān)系的對應(yīng)也是非常值得重視的。只有將內(nèi)外劃分妥當(dāng)才能使內(nèi)蘊(yùn)狀態(tài)發(fā)揮它應(yīng)有的作用;如果劃分失誤,在最糟糕的情況下系統(tǒng)中的對象是一個也不會減少的!兩者的對應(yīng)關(guān)系的維護(hù)和查找也是要花費(fèi)一定的空間(當(dāng)然這個比起不使用共享對象要小得多)和時間的,可以說享元模式就是使用時間來換取空間的。在Gof的書中是使用了B樹來進(jìn)行對應(yīng)關(guān)系查找優(yōu)化。


          總結(jié)
                也許你要長嘆一聲:這個享元模式未必太復(fù)雜了吧!這點(diǎn)是不得不承認(rèn)的,也許由于它的復(fù)雜,實(shí)際應(yīng)用也不是很多,這是我們更加無法看清他的真面目了。不過享元模式并不是雞肋,它的精髓——共享是對我們系統(tǒng)優(yōu)化非常有好處的,而且這種思想已經(jīng)別越來越多的應(yīng)用,這應(yīng)該就算是享元模式的應(yīng)用了吧。如果你已經(jīng)領(lǐng)會到了享元模式的精髓,那么也就是掌握了享元模式了!

              匆匆學(xué)完了享元模式,不知道理解上有沒有紕漏,希望大家能指正出來,一起共同進(jìn)步!其實(shí)我一直想使用一個實(shí)際系統(tǒng)中或者實(shí)踐中的例子來講解享元模式,可是畢竟自己的工作經(jīng)驗(yàn)太少了?。∮谑窍朐诰W(wǎng)上找一些靈感來,可是狂搜一陣子也沒有發(fā)現(xiàn)什么,于是就又落俗套的使用了一個比喻的例子。如果您對此深有體會的話,還煩請不吝賜教?。?/span>




           

          posted on 2011-08-02 14:15 HUIKK 閱讀(242) 評論(0)  編輯  收藏 所屬分類: Design Patterns
          主站蜘蛛池模板: 高邑县| 黄浦区| 荆门市| 呼伦贝尔市| 年辖:市辖区| 大兴区| 梁河县| 调兵山市| 台南县| 平和县| 广元市| 宜兰县| 永顺县| 平江县| 鄄城县| 福建省| 博兴县| 扎赉特旗| 修武县| 宣城市| 尚义县| 松潘县| 都昌县| 图片| 洪湖市| 航空| 沂源县| 图木舒克市| 灵寿县| 资兴市| 神木县| 高淳县| 茌平县| 南木林县| 平湖市| 清流县| 东兴市| 喜德县| 新兴县| 东方市| 昌邑市|