單例模式(二)

2022-09-06 05:21:10 字數 2782 閱讀 1083

目錄

正文

本文首先概述了單例模式,揭示了單例模式的應用場景和優缺點,最後我們給出了單例模式的幾種實現方式及注意事項。

回到頂部

單例模式是一種常用的軟體設計模式,其定義是單例物件的類只能允許乙個例項存在。

許多時候整個系統只需要擁有乙個的全域性物件,這樣有利於我們協調系統整體的行為。比如在某個伺服器程式中,該伺服器的配置資訊存放在乙個檔案中,這些配置資料由乙個單例物件統一讀取,然後服務程序中的其他物件再通過這個單例物件獲取這些配置資訊。這種方式簡化了在複雜環境下的配置管理。

單例的實現主要是通過以下兩個步驟

將該類的構造方法定義為私有方法,這樣其他處的**就無法通過呼叫該類的構造方法來例項化該類的物件,只有通過該類提供的靜態方法來得到該類的唯一例項;

在該類內提供乙個靜態方法,當我們呼叫這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就建立該類的例項並將例項的引用賦予該類保持的引用。

回到頂部

舉乙個小例子,在我們的windows桌面上,我們開啟了乙個**站,當我們試圖再次開啟乙個新的**站時,windows系統並不會為你彈出乙個新的**站視窗。,也就是說在整個系統執行的過程中,系統只維護乙個**站的例項。這就是乙個典型的單例模式運用。

繼續說**站,我們在實際使用中並不存在需要同時開啟兩個**站視窗的必要性。假如我每次建立**站時都需要消耗大量的資源,而每個**站之間資源是共享的,那麼在沒有必要多次重複建立該例項的情況下,建立了多個例項,這樣做就會給系統造成不必要的負擔,造成資源浪費。

再舉乙個例子,**的計數器,一般也是採用單例模式實現,如果你存在多個計數器,每乙個使用者的訪問都重新整理計數器的值,這樣的話你的實計數的值是難以同步的。但是如果採用單例模式實現就不會存在這樣的問題,而且還可以避免執行緒安全問題。同樣多執行緒的執行緒池的設計一般也是採用單例模式,這是由於執行緒池需要方便對池中的執行緒進行控制

從上述的例子中我們可以總結出適合使用單例模式的場景和優缺點:  

適用場景:

回到頂部

優點

缺點

回到頂部

1.餓漢式

// 餓漢式單例

public class singleton1

// 以自己例項為返回值的靜態的公有方法,靜態工廠方法

public static singleton1 getsingleton1()

}

我們知道,類載入的方式是按需載入,且載入一次。。因此,在上述單例類被載入時,就會例項化乙個物件並交給自己的引用,供系統使用;而且,由於這個類在整個生命週期中只會被載入一次,因此只會建立乙個例項,即能夠充分保證單例。

優點:這種寫法比較簡單,就是在類裝載的時候就完成例項化。避免了執行緒同步問題。

缺點:在類裝載的時候就完成例項化,沒有達到lazy loading的效果。如果從始至終從未使用過這個例項,則會造成記憶體的浪費。

2.懶漢式

// 懶漢式單例

public class singleton2

// 以自己例項為返回值的靜態的公有方法,靜態工廠方法

public static singleton2 getsingleton2()

return singleton2;}}

我們從懶漢式單例可以看到,單例例項被延遲載入,即只有在真正使用的時候才會例項化乙個物件並交給自己的引用。

這種寫法起到了lazy loading的效果,但是只能在單執行緒下使用。如果在多執行緒下,乙個執行緒進入了if (singleton == null)判斷語句塊,還未來得及往下執行,另乙個執行緒也通過了這個判斷語句,這時便會產生多個例項。所以在多執行緒環境下不可使用這種方式。

3.雙重加鎖機制

public class singleton

public static singleton getinstance()}}

return instance;}}

double-check概念對於多執行緒開發者來說不會陌生,如**中所示,我們進行了兩次if (singleton == null)檢查,這樣就可以保證執行緒安全了。這樣,例項化**只用執行一次,後面再次訪問時,判斷if (singleton == null),直接return例項化物件。

使用雙重檢測同步延遲載入去建立單例的做法是乙個非常優秀的做法,其不但保證了單例,而且切實提高了程式執行效率

優點:執行緒安全;延遲載入;效率較高。

4.靜態初始化

//阻止發生派生,而派生可能會增加例項

public sealed class singleton

public static singleton getinstance()

}

在實際應用中,c#與公共語言執行庫也提供了一種「靜態初始化」方法,這種方法不需要開發人員顯式地編寫執行緒安全**,即可解決多執行緒環境下它是不安全的問題。

回到頂部

當然,單例模式的實現方法還有很多。但是,這四種是比較經典的實現,也是我們應該掌握的幾種實現方式。

從這四種實現中,我們可以總結出,要想實現效率高的執行緒安全的單例,我們必須注意以下兩點:

單例模式 單例模式

餓漢式 急切例項化 public class eagersingleton 2.宣告靜態成員變數並賦初始值 類初始化的時候靜態變數就被載入,因此叫做餓漢式 public static eagersingleton eagersingleton new eagersingleton 3.對外暴露公共的...

設計模式 二 單例模式

建立乙個物件並不難,但當我們不得不為每新新增一種抽象類或介面而到處修改客戶 時,就不得不思考直接使用new建立物件帶來的高耦合。建立型別的模式將使用物件和 例項化物件 進行了分離。建立型別模式包括 單例模式 工廠方法模式 原型模式。下面先看單例模式 單例模式 保證乙個類在系統裡只有乙個例項化物件。應...

設計模式(二) 單例模式

單例模式 用來建立只能有乙個例項的物件。確保乙個類只有乙個例項,並提供乙個全域性訪問點。有的時候我們不希望乙個類被建立出多個物件,因為多個例項會帶來許多不好的影響。經典單例模式 public class singleinstance public static singleinstance geti...