設(shè)計(jì)模式之一單例設(shè)計(jì)模式

一、使用場(chǎng)景

單例設(shè)計(jì)模式是應(yīng)用最廣的設(shè)計(jì)模式,例如:當(dāng)創(chuàng)建一個(gè)對(duì)象需要消耗過(guò)多的資源,如要訪問(wèn)IO或數(shù)據(jù)庫(kù)等資源,這時(shí)就要考慮用單例模式;在一個(gè)應(yīng)用中,應(yīng)該只有一個(gè)ImageLoader實(shí)例,這個(gè)ImageLoader中又有線程池、緩存系統(tǒng)、網(wǎng)絡(luò)請(qǐng)求等,很消耗資源,一般用單例模式。

二、如何實(shí)現(xiàn)

1、構(gòu)造函數(shù)私有化。

2、通過(guò)靜態(tài)方法或者枚舉返回單例對(duì)象。

3、確保單例對(duì)象有且只有一個(gè),尤其是在多線程環(huán)境下。

4、確保單例對(duì)象在反序列化下不會(huì)重新構(gòu)建對(duì)象。

三、代碼實(shí)現(xiàn)

1、餓漢單例模式

public class Singleton {

? ? private static final Singleton instance=new Singleton();

? ? private Singleton() {

? ?}

? ? public static Singleton getInstance() {

? ? ? ? ? ? ? ? ? return instance;

? ? ?}

}

2、懶漢式

懶漢單例模式的優(yōu)點(diǎn)是單例只有在使用時(shí)才會(huì)初始化,在一定程度上節(jié)約了資源。缺點(diǎn)是第一次加載時(shí)需要及時(shí)進(jìn)行實(shí)例化,反應(yīng)稍慢,最大的問(wèn)題是每次調(diào)用getInstance都進(jìn)行同步,造成不必要的同步開(kāi)銷,不建議使用。

public class Singleton {

? ? ? private static Singleton instance;

? ? ? private Singleton(){

? ? }

? ? ? public static Synchronized Singleton getInstance(){

? ? ? ? ? ?if(instance==null){

? ? ? ? ? ? ? ? ? ?instance=new Singleton();

? ? ? ? ? }

? ? ? ? ?return instance;

? ? ?}

}

3、Double Check Load(DCL)

優(yōu)點(diǎn)是既能在需要時(shí)才初始化單例,又能保證線程安全,且單例模式初始化時(shí)調(diào)用getInstance不進(jìn)行同步鎖。缺點(diǎn)是在第一次加載時(shí)反應(yīng)稍慢,由于java 內(nèi)存模型的原因偶爾會(huì)加載失敗,在高并發(fā)環(huán)境下也存在一定缺陷,但是概率較小。除非代碼并發(fā)場(chǎng)景較復(fù)雜,或者在JDK 6版本以下,否則該種模式一般滿足條件。該種模式也是使用較多的模式。

public class Singleton {

? ? ? private static Singleton instance=null;

? ? ? private Singleton(){

? ?}

? ? ?public static Singleton getInstance(){

? ? ? ? ?if(instance==null){

? ? ? ? ? ? ? synchronized(Singleton.class){

? ? ? ? ? ? ? ? ? ? if(instance==null){

? ? ? ? ? ? ? ? ? ? ? ? ? ?instance=new Singleton();

? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? ? return instance;

? ? }

}

4、靜態(tài)內(nèi)部類單例模式

此種方法解決DCL模式不能在線程并發(fā)復(fù)雜情況下使用問(wèn)題,此為推薦使用模式。

public class Singleton {

? ? ?private Singleton() {

? ? }

? ? ?public static Singleton getInstance() {

? ? ? ? ? ? ?return SingletonHolder.singleton;

? ?}

/**

*靜態(tài)內(nèi)部類

*/

? ? ? private static class SingletonHolder {

? ? ? ? ? ?private static fina lSingleton singleton=new Singleton();

? ? }

}

5、枚舉單例

此種方法寫(xiě)法簡(jiǎn)單,線程安全,并且防止反序列化重新生成對(duì)象。

publc enum SingletonEnum{

INSTANCE;

}

以上構(gòu)建單例模式方法中,為了避免反序列化重新生成對(duì)象,加入以下方法

private Object readResolve() throws ObjectSteamException{

return instance;

}

6、使用容器實(shí)現(xiàn)單例

這種方式使得我們可以管理多種類型的單例,并且使用時(shí)可以用統(tǒng)一的接口進(jìn)行獲取操作,降低用戶使用成本,也對(duì)用戶隱藏了具體實(shí)現(xiàn),降低了耦合度。

public class SingletonManager {

? ? ?private static Map?objMap = new HashMap();

? ? ?private SingletonManager(){}

? ? ?public static void registerService(String key,Object instance){

? ? ? ? ? ? ? if(!objMap.containsKey(key)){

? ? ? ? ? ? ? ? ? ? ? ?objMap.put(key,instance);

? ? ? ? ?}

}

? ? ?public static ObjectgetService(String key){

? ? ? ? ? ? ? ? ? return objMap.get(key);

? ?}

}

不管以哪種方式實(shí)現(xiàn)單例模式,其核心都是構(gòu)造器私有化,并且通過(guò)靜態(tài)方法獲取唯一實(shí)例,在獲取過(guò)程中必須保證線程安全、防止反序列化重新生成實(shí)例等問(wèn)題。當(dāng)然,選擇那種方式,取決于項(xiàng)目本身。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容