android設(shè)計(jì)模式之單例模式詳解
這是我們最常見的一類模式,對這一類模式有一個(gè)通用的特點(diǎn)就是:
封裝創(chuàng)建的方式和過程。
這里所謂封裝就是隱藏的意思,對對象的創(chuàng)建方法和過程不可見,或者是虛擬的過程。
隱藏創(chuàng)建方式,就是如單例,工廠方法,隱藏創(chuàng)建過程則是指builder,原型,至于抽象工廠,我認(rèn)為他包含了以上兩種。
我們想想一個(gè)對象的創(chuàng)建有哪些步驟?
1、創(chuàng)建什么東西?--接口定義
2、誰創(chuàng)建? --決策類or幫助類
3、如何創(chuàng)建? --how,創(chuàng)建過程
4、什么時(shí)候創(chuàng)建? --創(chuàng)建時(shí)機(jī)的觸發(fā)
由此可知,創(chuàng)建型就是在上面幾個(gè)點(diǎn)做文章
我將單例模式放在最前面來講,是因?yàn)楹唵魏椭卑住?/P>
1、單例模式
gof原文這么講的:
Ensure a class only has one instance, and providea global point of access to it
有2點(diǎn):
a、僅且只能有1個(gè)實(shí)例
b、提供一個(gè)全局訪問點(diǎn)
就是說一個(gè)對象只能生成一次,然后可以全局個(gè)方法或者類去調(diào)用。
<有事離開,未完待續(xù)>
從上面描述就知道,我們一般在需要只用對象的一個(gè)實(shí)例的時(shí)候才用到這個(gè)模式,類似我們常說的全局對象,在j2ee中我們知道默認(rèn)spring初始化bean的時(shí)候都是單例的,我們也可以在配置文件中定義,如下:
<bean id="foo" class="foo" singleton="true" />
這告訴spring容器,foo的實(shí)例只會生成一次。
那么在android中,有哪些地方用到了單例模式呢?
我們知道一個(gè)手機(jī)中,打開輸入法,不管在哪打開,其實(shí)都是一個(gè)實(shí)例;Activity.java中有一個(gè)mSearchManager的對象它也是單例對象;如果是android原生系統(tǒng),有個(gè)全局搜索global,如果看android源碼,你會發(fā)現(xiàn)DisplayManagerGlobal,WindowManagerGlobal等等很多都是單例的,這些對象負(fù)責(zé)管理整個(gè)手機(jī)的運(yùn)行處理。我們來看 WindowManagerGlobal 的實(shí)現(xiàn):
public static WindowManagerGlobal getInstance() {
synchronized (WindowManagerGlobal.class) {
if (sDefaultWindowManager == null) {
sDefaultWindowManager = new WindowManagerGlobal();
}
return sDefaultWindowManager;
}
}
這樣系統(tǒng)保證了WindowManagerGlobal 對象的產(chǎn)生只會有一個(gè),在系統(tǒng)調(diào)用(決策對象)需要的時(shí)候,調(diào)用getInstance(全局訪問點(diǎn)),來生成new 。這是一個(gè)很完整的單例模式的實(shí)現(xiàn),一個(gè)很好的例子。
mSearchManager的實(shí)現(xiàn)也很有意思:
private void ensureSearchManager() {
if (mSearchManager != null) {
return;
}
mSearchManager = new SearchManager(this, null);
}
這里有人會說怎么這樣嗯,沒返回SearchManager對象啊,就是沒有決策類這個(gè)角色。其實(shí)他是有的,他的決策類就是我們常用的getSystemService,看代碼:
@Override
public Object getSystemService(String name) {
if (getBaseContext() == null) {
throw new IllegalStateException(
"System services not available to Activities before onCreate()");
}
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
return super.getSystemService(name);
}
其實(shí)這里getSystemService我們可以看做一個(gè)特殊的決策類,從以下代碼來看:
if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
我們改成:
public static SearchManager getInstance(){
ensureSearchManager();
return mSearchManager;
}
這就是一個(gè)單例模式。但從getSystemService整個(gè)代碼來看,確實(shí)工廠方法模式,這個(gè)我們在下面會講到。
根據(jù)對象創(chuàng)建時(shí)機(jī)的不同,單例模式有三種方式:
1、餓漢式 --就是實(shí)例在類加載的時(shí)候就生成
public class foo{
foo(){}
private static foo instance =new foo();
public static foo getlnstance(){
return instance;
}
}
2、懶漢式
public class foo{
foo(){}
private static foo instance = null ;
public static foo getlnstance(){
if(instance == null){
instance = new foo();
}
return instance;
}
}
3、注冊式
public static foo getInstance(String name) {
if(name == null) {
name = foo .class.getName();
System.out.println("name == null"+"--->name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (foo ) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
第一種和第二種方式區(qū)別在于創(chuàng)建時(shí)機(jī)的差異,而第三種則是如何創(chuàng)建有區(qū)別。
最后,問幾個(gè)問題:
1、android還有哪些其他的單例模式
2、launcher mode中有沒有單例模式的實(shí)現(xiàn)
3、單例模式的拓展中,數(shù)據(jù)庫連接池屬于哪種方式的變異(衍生).
4、三種方式的單例模式的優(yōu)缺點(diǎn)有哪些?一般用途區(qū)別在哪?。
相關(guān)文章
Android實(shí)現(xiàn)一個(gè)倒計(jì)時(shí)自定義控件
大家好,本篇文章主要講的是Android實(shí)現(xiàn)一個(gè)倒計(jì)時(shí)自定義控件,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-02-02Android頁面中可編輯與不可編輯切換的實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于在Android頁面中可編輯與不可編輯切換的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Android自定義控件EditText實(shí)現(xiàn)清除和抖動(dòng)功能
這篇文章主要為大家詳細(xì)介紹了Android自定義控件EditText實(shí)現(xiàn)清除和抖動(dòng)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12android引導(dǎo)用戶開啟自啟動(dòng)權(quán)限的方法
今天小編就為大家分享一篇android引導(dǎo)用戶開啟自啟動(dòng)權(quán)限的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07Android實(shí)現(xiàn)簡易計(jì)算器(可以實(shí)現(xiàn)連續(xù)計(jì)算)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡易計(jì)算器,可以實(shí)現(xiàn)連續(xù)計(jì)算,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03Android ScrollView 下嵌套 ListView 或 GridView出現(xiàn)問題解決辦法
這篇文章主要介紹了ScrollView 下嵌套 ListView 或 GridView 會發(fā)列表現(xiàn)數(shù)據(jù)只能顯示一行。因?yàn)樗麄兌际菨L動(dòng)結(jié)構(gòu),兩個(gè)滾動(dòng)條放到一起就會引起沖突,這里提供解決辦法相關(guān)資料,需要的朋友可以參考下2017-07-07Android自定義View實(shí)現(xiàn)簡單的圓形Progress效果
這篇文章主要介紹了Android自定義View實(shí)現(xiàn)簡單的圓形Progress效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09android 多點(diǎn)觸摸圖片縮放的具體實(shí)現(xiàn)方法
2013-06-06