Android中的享元模式

設(shè)計(jì)模式.png

前言

又來梳理知識(shí)點(diǎn)啦!

在有的時(shí)候我們要多次使用某個(gè)類中的公有實(shí)例方法,我們通常的做法是,先new一個(gè)該類的實(shí)例,然后再調(diào)用該類的這個(gè)方法砰左,調(diào)用完畢后這個(gè)類也就變成垃圾。這種調(diào)用方式如果出現(xiàn)的頻率很高场航,會(huì)在對象生成和內(nèi)存占用上浪費(fèi)很多的資源缠导,一個(gè)對象的創(chuàng)建和銷毀是很占資源的。

于是溉痢,偉大的程序員們想到一個(gè)好辦法僻造,嘗試重用現(xiàn)有的同類對象,如果未找到匹配的對象孩饼,則創(chuàng)建新對象髓削。經(jīng)典的享元模式中,是使用一個(gè)map來存儲(chǔ)對象镀娶,相當(dāng)于是一個(gè)對象工廠立膛,客戶端每次都從享元對象工廠中獲取對象。

定義

使用共享對象可有效的支持大量的細(xì)粒度對象

使用場景

  1. 系統(tǒng)中存在大量的相似對象
  2. 對象沒有特定的身份梯码,狀態(tài)都較接近
  3. 需要緩沖池的場景

使用方法

享元模式是一種思想宝泵,一種避免多次重復(fù)創(chuàng)建對象的編程思想。

我們主要是要?jiǎng)?chuàng)建一個(gè)享元工廠忍些,來生產(chǎn)我們的享元類鲁猩。這樣的享元工廠有N種寫法坎怪,我們常見的是使用map來構(gòu)造享元工廠罢坝,來看一個(gè)享元工廠的demo

import java.util.HashMap;

public class ShapeFactory {
   private static final HashMap<String, Shape> circleMap = new HashMap();

   //使用傳統(tǒng)的map來管理對象
   public static Shape getObj(String color) {
      Circle circle = (Circle)circleMap.get(color);

      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

Android中的享元模式應(yīng)用

應(yīng)用的話,若我說,我們編寫的ViewHolder都可以歸類為享元工廠的存儲(chǔ)器嘁酿。幾乎到處是應(yīng)用隙券,不過最明顯的是Handler中Message的應(yīng)用。

例如我們發(fā)送個(gè)0給handler自己闹司。

handler.obtainMessage(0).sendToTarget();

我們進(jìn)去看Handler的源碼娱仔,obtainMessage如下

    public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
    {
        return Message.obtain(this, what, arg1, arg2, obj);
    }

我們發(fā)現(xiàn),其中調(diào)用了Message.obtain游桩,我們再去看Message的實(shí)現(xiàn)

    public static Message obtain(Handler h, int what, 
            int arg1, int arg2, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;
        m.obj = obj;

        return m;
    }
    
    //獲取一個(gè)空message
    public static Message obtain() {
        synchronized (sPoolSync) {
            //從對象Message中獲取message
            if (sPool != null) {   //private static Message sPool;
                Message m = sPool;
                sPool = m.next;
                //清空message屬性
                m.next = null;
                m.flags = 0; // clear in-use flag 
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

我們可以看到牲迫,sPool指向的是一個(gè)鏈表,其實(shí)這個(gè)鏈表是存儲(chǔ)我們用過的Message的借卧,當(dāng)我們obtain一個(gè)Message的時(shí)候盹憎,會(huì)去取鏈表中的第一個(gè),并把sPool指向下一個(gè)铐刘,同時(shí)把取到的置空陪每。

    /*Message的回收方法*/
    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }

    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

    /*將用過的Message放入鏈表中*/
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

我們可以知道Message的享元模式不是使用的傳統(tǒng)的map方式,而是自己構(gòu)建一個(gè)鏈表镰吵,靈活使用我們的享元模式思想才是重點(diǎn)檩禾。


謝謝大家閱讀,如有幫助疤祭,來個(gè)喜歡或者關(guān)注吧盼产!


本文作者:Anderson/Jerey_Jobs

博客地址 : 夏敏的博客/Anderson大碼渣/Jerey_Jobs

簡書地址 : Anderson大碼渣

CSDN地址 : Jerey_Jobs的專欄

github地址 : Jerey_Jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市勺馆,隨后出現(xiàn)的幾起案子辆飘,更是在濱河造成了極大的恐慌,老刑警劉巖谓传,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜈项,死亡現(xiàn)場離奇詭異,居然都是意外死亡续挟,警方通過查閱死者的電腦和手機(jī)紧卒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诗祸,“玉大人跑芳,你說我怎么就攤上這事≈甭” “怎么了博个?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長功偿。 經(jīng)常有香客問我盆佣,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任共耍,我火速辦了婚禮虑灰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痹兜。我一直安慰自己穆咐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布字旭。 她就那樣靜靜地躺著对湃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遗淳。 梳的紋絲不亂的頭發(fā)上熟尉,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機(jī)與錄音洲脂,去河邊找鬼斤儿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恐锦,可吹牛的內(nèi)容都是我干的往果。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼一铅,長吁一口氣:“原來是場噩夢啊……” “哼陕贮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起潘飘,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤肮之,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后卜录,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戈擒,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年艰毒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筐高。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丑瞧,死狀恐怖柑土,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绊汹,我是刑警寧澤稽屏,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站西乖,受9級特大地震影響狐榔,放射性物質(zhì)發(fā)生泄漏坛增。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一荒叼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧典鸡,春花似錦被廓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至球碉,卻和暖如春蜓斧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背睁冬。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工挎春, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豆拨。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓直奋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親施禾。 傳聞我的和親對象是個(gè)殘疾皇子脚线,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容