設計模式 單件模式

2021-06-28 11:55:05 字數 2383 閱讀 3330

2023年1月29日16:02:59

單件模式是用來保證共有資源唯一性的設計模式,舉個例子吧,假如我們是藝人,我們在同乙個經紀人的協助下開展工作,我們可以委託這個經紀人做一些事情,但是我們不能委託經紀人在幫你做報表的同時幫我訂外賣。用程式猿的語言來表達就是,我們可能在多處地方持有對同一資源的引用。由於資源一半都是用類來封裝,比如印表機,我們通過印表機驅動的類來使用印表機資源,所以我們的問題轉化為保證類的例項物件的唯一性。

這樣 我們就面臨了兩個選擇

1系統持有乙個全域性物件

2使用單件模式

上述的方案一顯然不可行,原因1增加了全域性物件的攻擊視窗,在系統的所有地方都可以訪問這個共有資源,這樣出錯的可能性大大增加,並且修復bug的難度也翻倍了

2消耗系統資源,全域性物件在系統的生命週期裡都占有資源,消耗資源很多。(3全域性物件是歸jvm管理的,可能存在建立問題,這點是書上寫的,我沒能理解)

上面第乙個是關鍵,第二點可以用延遲建立來緩解一下資源消耗問題。

那麼接下來的問題就是怎麼使用單件模式。

一種常用的方案是私有化構造器,然後公開乙個獲取例項的靜態方法

public class singleton 

public static singleton getinstance()

}

私有化的構造器避免了程式設計師在類外部例項化物件,我們在類記憶體乙個靜態的物件,我們之後獲取的物件就是儲存的這個靜態物件。 

這樣問題來了,這不是和之前說的全域性物件不是很像麼,但是注意這個物件是jvm管理的,對於程式來說我們在不使用的時候並沒有存對這樣乙個物件的引用,也就是沒有那麼大的攻擊視窗。

另一外需要討論的問題是靜態物件怎麼建立

1需要的時候建立

public static singleton getinstance()

return singletonobject;

}

這屬於延遲建立的方法,也就是在首次需要用的時候類才被建立 

但是這樣的方法在多執行緒的時候可能會出現問題,比如現在有2個執行緒同時需要獲取這個物件,執行緒a判斷物件為空,此時切換到b執行緒,執行緒b判斷物件為空,然後切換到a執行緒,a執行緒新建物件,a執行緒返回物件,此時切換回b執行緒,b執行緒新建物件,b執行緒 返回物件。這樣程式同時出現了2個單件物件,這樣明顯是錯的

於是程式需要改進

改進方案一

public synchronized static singleton getinstance()

return singletonobject;

}

用同步關鍵字限制同時只有1個執行緒能使用這個方法,保證這個方法的原子性,這是乙個解決方案,但是存在效率損失的問題,這樣的方案在物件獲取的頻率比較低的時候適用

改進方案二

在建立物件的時候進入同步區

public static singleton getinstance()}}

return singletonobject;

}

對於多執行緒的時候也存在乙個需要注意的問題,裡面存在是每個程式可能有自己的記憶體物件備份,所以在例項同步的時候需要對需要加鎖的物件新增volatile關鍵字 

詳細參見volatile的解析        這個應該是與作業系統中同步的metrux變數類似

private volatile static singleton  singletonobject;

這樣最小限度的減少了同步的損耗

我在查閱資料的時候發現乙份這樣的文件

裡面提出的核心問題是多執行緒對物件的例項化可能存在問題, 參見c++的物件例項化,物件例項化分分配記憶體和物件初始化2部分,在雙重鎖定的時候,在分配記憶體的時候就可能返回了鎖,這樣第二線程可能返回乙個未初始化變數的物件。(雖然我還是沒有完全接受,但是還是列出來,希望大神指點一下)

2提前宣告

private static singleton  singletonobject= new singleton();

這樣的方案避免了之前所說的所有同步問題,也只有在類初次調入記憶體的時候才會建立靜態物件,總的來說是最好的方案。

3用工廠模式建立

這個方案是將建立物件的職責從jvm拿到工廠之中,內部實現可以參見之前討論的兩點,在遇到多執行緒的時候 還是採用提前宣告的方案。

工廠可以採取全域性變數的方式實現,這樣雖然記憶體消耗存在,但是減少了攻擊視窗。

當然工廠也可以用單件模式實現,不過看起來就有點變扭。

設計模式 單件模式

1 1 singleton.h ifndef singleton h define singleton h include using namespace std class singleton 構構函式,防止拷貝構造另乙個例項,作為protected singleton 析構函式,作為protec...

設計模式 單件模式

保持單一物件有時非常必要,尤其是資源類,比如視窗資源,登錄檔等等,所謂的單件模式的定義是 確保乙個類只有乙個例項,並提供乙個全域性的訪問點。其類圖雖說比較簡單,但單例模式還是有很多陷阱的。首先,給出單例模式的經典的懶漢式寫法 懶漢式 需要例項物件時才建立,延遲建立 class single pubi...

設計模式 單件模式

單件模式 singleton 也叫單例模式,是一種建立型模式。它確保乙個類只有乙個例項,並提供全域性訪問。singleton中uniqueinstance類變數持有唯一的單件例項,getinstance 是靜態方法,可以通過類名在任何需要的地方使用它,與訪問全域性變數一樣,但是可以延遲例項化。餓漢式...