1.意圖
運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對象。
2.結(jié)構(gòu)
這是一個(gè)完整的享元模式結(jié)構(gòu)圖。
客戶端通過享元工廠獲取享元對象,享元對象的創(chuàng)建則根據(jù)工廠的享元池來控制,如果有享元池中沒有這個(gè)對象,則創(chuàng)建這個(gè)對象并保存到享元池中,如果享元池中有這個(gè)對象,則直接使用這個(gè)對象。因?yàn)橄碓獙ο笤诠蚕淼耐瑫r(shí),說明它重用屬性的不變性,不然都是變化的東西,不存在共享,這些不變得屬性我們稱之為內(nèi)部狀態(tài),獨(dú)立與外部場景。而另外一些屬性,可以根據(jù)外部場景變化的,我們稱之為外部狀態(tài),在上圖中我們也看到,我們可以通過Operation改變外部狀態(tài)。
Android中SQLiteCompiledSql的使用,其實(shí)是很多數(shù)據(jù)庫系統(tǒng)典型的實(shí)現(xiàn)。從應(yīng)用啟動(dòng),通過各種數(shù)據(jù)庫操作,我們不知道進(jìn)行了多少次的查詢操作,而這些操作中又有相當(dāng)一部分sql語句是相同的,這些編譯后的sql編譯對象其實(shí)是一樣的,是可以共用共享的,其實(shí)就是緩存。SQLiteCompiledSql就是這樣的一個(gè)需要共享的享元對象,畫出相關(guān)的UML圖如下:
其中SqliteDatabase中的mCompiledQuerie就是存放享元對象的容器。
通過這種方式大大減少了sql編譯對象的創(chuàng)建,提高了數(shù)據(jù)庫操作的性能。
3.代碼
享元對象類SQLiteCompiledSql,主要是內(nèi)部狀態(tài)sql語句:
class SQLiteCompiledSql {
private String mSqlStmt = null;
native_compile(sql);
native_finalize();
}
享元工廠類:
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) {
//省略具體代碼
}
}
其他類幾個(gè)相關(guān)類是對這個(gè)集合的操作相關(guān),和享元模式?jīng)]有什么實(shí)質(zhì)性的關(guān)系,代碼省略。
4.效果
(1).結(jié)構(gòu)型模式;
(2).節(jié)約存儲(chǔ)的方法:用共享減少內(nèi)部狀態(tài)的消耗,用計(jì)算時(shí)間換取對外部狀態(tài)的存儲(chǔ);
(3).緩沖。