學習設計模式,必然會談到單例模式,由於它是一種很經常使用的軟件設計模式,本節開始學習單例模式,首先解釋單例模式的定義、分類,接着實例介紹餓漢式單例模式類、懶漢式單例模式類、在多線程中的應用及它們的區別,最後列舉一個單例模式的實例,以供參考。設計模式
定義:安全
單例模式:保證一個類僅有一個實例,並提供一個全局訪問點。服務器
相關解釋:在應用單例模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只須要擁有一個的全局對象,這樣有利於咱們協調系統總體的行爲。好比在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,而後服務進程中的其餘對象再經過這個單例對象獲取這些配置信息。這種方式簡化了在複雜環境下的配置管理。多線程
單例模式通常分爲兩大類:函數
一、餓漢式單例:靜態初始化的方式是在本身被加載時就將本身實例化;學習
二、懶漢式單例:在第一次被引用時,纔會將本身實例化。this
實現:spa
實現單例模式的思路是:一個類能返回對象一個引用(永遠是同一個)和一個得到該實例的方法(必須是靜態方法,一般使用getInstance這個名稱);當咱們調用這個方法時,若是類持有的引用不爲空就返回這個引用,若是類保持的引用爲空就建立該類的實例並將實例的引用賦予該類保持的引用;同時咱們還將該類的構造函數定義爲私有方法,這樣其餘處的代碼就沒法經過調用該類的構造函數來實例化該類的對象,只有經過該類提供的靜態方法來獲得該類的惟一實例。線程
餓漢式單例模式類: 設計
//餓漢式 class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; } }
懶漢式單例模式類:
//懶漢式 class Singleton { private static Singleton instance; private Singleton() { } public static Singleton GetInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
在多線程中應用:
在多線程的應用場合下必須當心使用。若是當惟一實例還沒有建立時,有兩個線程同時調用建立方法,那麼它們同時沒有檢測到惟一實例的存在,從而同時各自建立了一個實例,這樣就有兩個實例被構造出來,從而違反了單例模式中實例惟一的原則。 解決這個問題的辦法是爲指示類是否已經實例化的變量提供一個互斥鎖(雖然這樣會下降效率)。
代碼實例:
class Singleton { private static Singleton instance; private static readonly object obj = new object(); private Singleton() { } public static Singleton GetInstance() { if (instance == null) { lock (obj) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
餓漢式和懶漢式區別:
餓漢式,即靜態初始化式,它是在類第一次加載就實例化的對象,因此須要提早佔用系統資源。
懶漢式:雖然不會有餓漢式的問題,可是它會面臨着多線程訪問的安全性問題,須要作雙重鎖定的處理才能保證系統安全,一樣會下降效率。
具體如何使用,就須要取決育實際,沒有誰好誰劣。
實例:
列舉一個完整的例子,謹供參考。功能:新建一個Form1窗體,Form1窗體中有一個button控件,彈出一個FormToolbox窗體。要求:每次只能彈出一個FormToolbox窗體,只有在關閉FormToolbox窗體時才容許系統從新彈出新的FormToolbox窗體。
貼代碼:
//Form1窗體: private void Form1_Load(object sender, EventArgs e) { this.IsMdiContainer = true; } private void button1_Click(object sender, EventArgs e) { FormToolbox.GetInstance().Show(); } //FormToolbox窗體: public partial class FormToolbox : Form { private static FormToolbox ftb = null; private FormToolbox() { InitializeComponent(); } public static FormToolbox GetInstance() { if (ftb == null || ftb.IsDisposed) { ftb = new FormToolbox(); ftb.MdiParent = Form1.ActiveForm; } return ftb; } }
到此,單例模式講解完畢。
補充:
正如一位園友fsllsf所說,還有一種方式:
C#與公共語言運行庫提供了一種「靜態初始化」方法,這種方法不須要開發人員顯式地編寫線程安全代碼,便可解決多線程環境下它是不安全的問題。
public sealed class Singleton { private static readonly Singleton instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; } }