【設計模式】享元模式(Flyweight)

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   使用   ar   java   for   

摘要:

1.本文將詳細介紹享元模式的原理和實際代碼中特別是Android系統代碼中的應用。

綱要:

1. 引入享元模式

2. 享元模式的概念及優缺點介紹

3. 享元模式在Android源碼中的應用

1.先來一個段子:

GG每天給MM至少發一條簡訊,而且每天入睡前是必有一條簡訊的,往往是一些瑣事和一些比較肉麻的情話。開始的一個月,GG還對此是樂不可支,隨著時間的推移,那些肉麻的話說了很多遍,自己也覺得厭煩了,而且更讓人不可忍耐的是這些肉麻的情話每次都要重複的輸入。GG把這一煩心事告訴了自己的好友K,K說,“你這個大傻瓜,怎麼不把一些你常用的話存放在你的手機中,這樣,要用的時候,直接拿來用就行了”,傻GG一聽,頓時覺得醍醐灌頂,於是立即在手機中存放入了“寶貝兒,晚安喔”、“你是我天使”,“寶貝兒,我永遠的愛你”等話語。(摘自Android大話設計模式)

2.享元模式介紹2.1什麼是享元模式?

為了節約記憶體資源,把具有重複性質的執行個體進行統一管理(結合Factory模式),使用時對象一般不建立新執行個體,只進行引用。Flyweight本是體育上的一個術語,用來表示輕量級。Flyweight,飛翔般的重量,說明使用它會使代碼變得“輕”(指記憶體消耗方面)起來。

2.2享元模式有什麼好處?

上面已經提到了,它最大也是唯一的好處就是:“輕”。享元能夠節省重複執行個體的記憶體消耗。舉兩個最經典的例子。

1、26個英文字母的點陣顯示資料。我們使用它們的時候,如果每次使用都建立新的字母執行個體,那記憶體浪費是很嚴重的。我們可以很容易的想到,將這26個點陣資料個建立一個執行個體,並專門用一個類管理起來。當使用者需要使用的時候,給他們這些執行個體的引用,這樣就能大大節省記憶體消耗了。

2、畫畫。假設我能畫的圖形是有限的(圓,長方形,棱形,梯形等),畫畫就是把這些圖形不斷的往上貼圖。當我一幅畫有上千個圖案的時候,享元模式就成為了很好的減少記憶體消耗的解決方案。我們把固定的圖形都只建立一個執行個體,等要畫的時候,使用它們的引用“作畫”即可。

不過這個畫畫的例子就有問題了:這些獨立圖形的位置,大小,顏色都不一樣,而執行個體只有一個,這樣畫出來豈不是都擠一塊去了?這裡是享元模式的關鍵的地方:區分內蘊態和外蘊態。簡單說就是:一部分(圖形)共用(稱為內部儲存或內部狀態),一部分(大小,位置,顏色)不公享(稱為外部儲存或外部狀態)。把這個概念加進去,享元模式就靈活多了。

3.源碼實戰:3.1String:

沒想到吧!String用到了享元模式。其實我也沒想到。就我個人理解,與其說String使用享元模式,不如說是用到了它的思想,畢竟它的實現不是通過活生生的Java代碼。下面一起來看一下:

String s0=”abc”;String s1=”abc”;String s2=”a” + “bc”;System.out.println( s0==s1 );System.out.println( s0==s2 );

 

結果為:

truetrue

我們都知道,String是一種對象(非基礎類型,下同),對象的==比較的是和指向的記憶體有關的。如果兩個對象指向的是同一個資料,那他們是相等的(Java語言是不支援重載的,所以沒有例外情況)。

但上面的寫法不應該是三個獨立的資料區段嗎?這裡就涉及到常量池。

常量池(constant pool)指的是在編譯期被確定,並被儲存在已編譯的.class檔案中的一些資料。它包括了關於類、方法、介面等中的常量,也包括字串常量。 這些字串對於編譯器來說,都是同樣的常量字串,所以編譯器把他們簡化成了一條資料,從而最佳化了記憶體使用量。這和享元模式的思想如出一轍。

如果我們這樣寫:

String s0=”abc”;String s1= new String(“abc”);System.out.println( s0==s1 );

結果為:

false

為什麼會這樣?因為s1等號右邊不是常量字串,而是執行個體化操作,人家編譯器不認這種非靜態東西。這也說明了一點,享元需要專門的類來管理,否則就會出現上面那種不適用的情況。一般來說都是用Factory。

3.2SQLiteCompiledSql:

(參考Android設計模式系列(6)--SDK源碼之享元模式 http://www.cnblogs.com/qianxudetianxia/archive/2011/08/10/2133659.html)

Android中SQLiteCompiledSql的使用,其實是很多資料庫系統典型的實現。從應用啟動,通過各種資料庫操作,我們不知道進行了多少次的查詢操作,而這些操作中又有相當一部分sql語句是相同的,這些編譯後的sql編譯對象其實是一樣的,是可以共用共用的,其實就是緩衝。SQLiteCompiledSql就是這樣的一個需要共用的享元對象。

UML圖:

其中SQLiteCompiledSql就是被管理享元對象,主要是內部狀態sql語句:

class SQLiteCompiledSql {    private String mSqlStmt = null;    native_compile(sql);    native_finalize();}

享元對象只是存放固定內容的執行個體,具體實現精華在管理享元對象的工廠中。

SqliteDatabase就是管理享元對象的工廠,它裡面的mCompiledQuerie就是存放享元對象的容器。通常都是使用HashMap(HashTable的替代品,詳細http://oznyang.iteye.com/blog/30690)進行儲存。通過這種方式大大減少了sql編譯對象的建立,提高了資料庫操作的效能。

public class SQLiteDatabase{    Map<String, SQLiteCompiledSql> mCompiledQueries = Maps.newHashMap();    SQLiteCompiledSql getCompiledStatementForSql(String sql) {        SQLiteCompiledSql compiledStatement = null;        boolean cacheHit;        synchronized(mCompiledQueries) {           if (mMaxSqlCacheSize == 0) {            return null;           }            cacheHit = (compiledStatement = mCompiledQueries.get(sql)) != null;       }        if (cacheHit) {        mNumCacheHits++;        } else {            mNumCacheMisses++;        }        return compiledStatement;    }    private void deallocCachedSqlStatements() {        synchronized (mCompiledQueries) {            for (SQLiteCompiledSql compiledSql : mCompiledQueries.values()) {               compiledSql.releaseSqlStatement();            }            mCompiledQueries.clear();        }    }    void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) {    //省略具體代碼    }}

大體享元工廠都是這樣一個結構:

HashMap:用作儲存(就和String的常量池一樣)

get方法:得到享元對象的引用

add方法:增加新的享元對象,用作初始化,一般使用者不會接觸到。也有更靈活的享元模式使用會動態增加HashMap沒有的享元對象(設計模式是死的,人寫出來的代碼是活的,怎麼用全憑大家)。

dealloc方法:釋放所有的享元對象,Java有自己的記憶體回收機制,這個可選。

著作權,轉載請註明出處:

http://www.cnblogs.com/sickworm/p/4016026.html 

【設計模式】享元模式(Flyweight)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.