国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

c#設(shè)計模式之單例模式的實(shí)現(xiàn)方式

2020-01-23 20:46:35
字體:
供稿:網(wǎng)友

場景描述

單例模式對于我們來說一點(diǎn)也不模式,是一個常見的名稱,單例模式在程序中的實(shí)際效果就是:確保一個程序中只有一個實(shí)例,并提供一個全局訪問點(diǎn),節(jié)省系統(tǒng)資源

單例模式無論是在實(shí)際開發(fā)中還是在軟件應(yīng)用中比較常見,比如,windows系統(tǒng)的任務(wù)管理器、IIS的HttpApplication、實(shí)際項目中的日志組件等等

實(shí)現(xiàn)方式

單例模式為了實(shí)現(xiàn)一個實(shí)例,那么只有不把實(shí)例創(chuàng)建暴露出去,只通過類本身來創(chuàng)建實(shí)例,為了實(shí)現(xiàn)效果,需要定義一個私有構(gòu)造函數(shù)

單例模式實(shí)現(xiàn)方式有:餓漢式、懶漢式、雙重驗(yàn)證式、靜態(tài)內(nèi)部類

下面分別對每一種實(shí)現(xiàn)方式做一個簡單的實(shí)例,以及其優(yōu)缺點(diǎn)

餓漢式

/// <summary> /// 創(chuàng)建一個 Singleton 類(餓漢式) /// 這種方式比較常用,但容易產(chǎn)生垃圾對象。 ///優(yōu)點(diǎn):沒有加鎖,執(zhí)行效率會提高。 ///缺點(diǎn):類加載時就初始化,浪費(fèi)內(nèi)存。 ///它基于 classloder 機(jī)制避免了多線程的同步問題,不過,instance 在類裝載時就實(shí)例化, ///雖然導(dǎo)致類裝載的原因有很多種,在單例模式中大多數(shù)都是調(diào)用 getInstance 方法, ///但是也不能確定有其他的方式(或者其他的靜態(tài)方法)導(dǎo)致類裝載,這時候初始化 instance 顯然沒有達(dá)到 lazy loading 的效果。 /// </summary> public class SingleObject {  //創(chuàng)建 SingleObject 的一個對象  private static SingleObject instance = new SingleObject();  //讓構(gòu)造函數(shù)為 private,這樣該類就不會被實(shí)例化  private SingleObject() {   Console.WriteLine("我被創(chuàng)建了.餓漢式");  }  //獲取唯一可用的對象  public static SingleObject GetInstance()  {   return instance;  }  public void ShowMessage()  {   Console.WriteLine("Hello World.餓漢式");  } }

懶漢式

/// <summary> /// 創(chuàng)建一個 Singleton 類(懶漢式) /// 這種方式具備很好的 lazy loading,能夠在多線程中很好的工作,但是,效率很低,99% 情況下不需要同步。 /// 優(yōu)點(diǎn):第一次調(diào)用才初始化,避免內(nèi)存浪費(fèi)。 /// 缺點(diǎn):懶漢式在單個線程中沒有問題,但多個線程同事訪問的時候就可能同事創(chuàng)建多個實(shí)例,而且這多個實(shí)例不是同一個對象。 /// </summary> public class SingleObject1 {  //創(chuàng)建 SingleObject 的一個對象  private static SingleObject1 instance;  //讓構(gòu)造函數(shù)為 private,這樣該類就不會被實(shí)例化  private SingleObject1() { }  //獲取唯一可用的對象  public static SingleObject1 GetInstance()  {   if (instance == null)   {    instance = new SingleObject1();    Console.WriteLine("我被創(chuàng)建了.懶漢式");   }   return instance;  }  public void ShowMessage()  {   Console.WriteLine("Hello World.懶漢式");  } }

雙重驗(yàn)證式

/// <summary> /// 創(chuàng)建一個 Singleton 類(雙重驗(yàn)證) /// 這種方式具備很好的 lazy loading,能夠在多線程中很好的工作,但是,效率很低,99% 情況下不需要同步。 /// 優(yōu)點(diǎn):第一次調(diào)用才初始化,避免內(nèi)存浪費(fèi),線程安全。 /// 缺點(diǎn):必須加鎖 synchronized 才能保證單例,但加鎖會影響效率。 /// </summary> public class SingleObject2 {  //創(chuàng)建 SingleObject 的一個對象  private static SingleObject2 instance;  // 定義一個標(biāo)識確保線程同步  private static readonly object locker = new object();  //讓構(gòu)造函數(shù)為 private,這樣該類就不會被實(shí)例化  private SingleObject2() { }  //獲取唯一可用的對象  public static SingleObject2 GetInstance()  {   //// 如果為空,那么就加鎖,創(chuàng)建實(shí)例   if (instance == null)   {    lock (locker)    {     //// 枷鎖成功后,在做一次非空判斷,避免在加鎖期間以創(chuàng)建了實(shí)例而導(dǎo)致重復(fù)創(chuàng)建     if (instance == null)     {      instance = new SingleObject2();      Console.WriteLine("我被創(chuàng)建了.雙重驗(yàn)證");     }    }   }   return instance;  }  public void ShowMessage()  {   Console.WriteLine("Hello World.雙重驗(yàn)證");  } }

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

/// <summary> /// 創(chuàng)建一個 Singleton 類(靜態(tài)內(nèi)部類)  /// 這種方式不用加鎖,在效率上和內(nèi)存使用上都比較優(yōu)秀 /// 克服了餓漢模式的不足餓漢模式執(zhí)行效率高,由于在類加載的時候初始化導(dǎo)致內(nèi)存浪費(fèi) /// </summary> public class SingletonStatic {  /// <summary>  /// 內(nèi)部類  /// </summary>  public class SingletonStaticInner  {   /// <summary>   /// 當(dāng)一個類有靜態(tài)構(gòu)造函數(shù)時,它的靜態(tài)成員變量不會被beforefieldinit修飾   /// 就會確保在被引用的時候才會實(shí)例化,而不是程序啟動的時候?qū)嵗?  /// </summary>   static SingletonStaticInner() { }   /// <summary>   /// 實(shí)例化   /// </summary>   internal static SingletonStatic singletonStatic = new SingletonStatic();  }  /// <summary>  /// 私有構(gòu)造函數(shù)  /// </summary>  private SingletonStatic() {   Console.WriteLine("我被創(chuàng)建了.靜態(tài)內(nèi)部類");  }  /// <summary>  /// 獲取實(shí)例  /// </summary>  /// <returns></returns>  public static SingletonStatic GetInstance()  {   return SingletonStaticInner.singletonStatic;  }  public void ShowMessage()  {   Console.WriteLine("Hello World.靜態(tài)內(nèi)部類");  } }

每一種創(chuàng)建方式測試

創(chuàng)建一個控制臺程序,通過多線程對每一種實(shí)現(xiàn)方式使用,查看其實(shí)例次數(shù)分析:

/* 介紹意圖:保證一個類僅有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn)。主要解決:一個全局使用的類頻繁地創(chuàng)建與銷毀。何時使用:當(dāng)您想控制實(shí)例數(shù)目,節(jié)省系統(tǒng)資源的時候。如何解決:判斷系統(tǒng)是否已經(jīng)有這個單例,如果有則返回,如果沒有則創(chuàng)建。關(guān)鍵代碼:構(gòu)造函數(shù)是私有的。應(yīng)用實(shí)例:典型的已有應(yīng)用:1、windows的任務(wù)管理器等2、IIS的HttpApplication,所有的HttpModule都共享一個HttpApplication實(shí)例在項目中的實(shí)際使用場景:1、日志組件2、多線程線程池管理3、網(wǎng)站計數(shù)器4、配置文件管理  */ class Program {  static void Main(string[] args)  {   TaskFactory taskFactory = new TaskFactory();   List<Task> taskList = new List<Task>();   //// 測試--餓漢式    for (int i = 0; i < 5; i++)   {    taskList.Add(taskFactory.StartNew(() =>    {     SingleObject.GetInstance();    }));   }   //// 測試--懶漢式    for (int i = 0; i < 5; i++)   {    taskList.Add(taskFactory.StartNew(() =>    {     SingleObject1.GetInstance();    }));   }   //// 測試--雙重驗(yàn)證    for (int i = 0; i < 5; i++)   {    taskList.Add(taskFactory.StartNew(() =>    {     SingleObject2.GetInstance();    }));   }   //// 測試--靜態(tài)內(nèi)部類    for (int i = 0; i < 5; i++)   {    taskList.Add(taskFactory.StartNew(() =>    {     SingletonStatic.GetInstance();    }));   }   Console.ReadLine();  } }

運(yùn)行結(jié)果:

  

通過結(jié)果可以看出:懶漢式實(shí)際創(chuàng)建了2個實(shí)例,所以在多線程中,懶漢式有線程不安全問題

總結(jié)

根據(jù)單例模式是每一種實(shí)現(xiàn)方式對比分析,在實(shí)際使用過程中:

如果是單線程應(yīng)用環(huán)境,建議可以采用懶漢模

如果是多線程應(yīng)用環(huán)境,建議采用靜態(tài)內(nèi)部類方式

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對武林網(wǎng)的支持。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 龙山县| 德安县| 普格县| 萝北县| 古浪县| 藁城市| 武宁县| 静宁县| 武邑县| 临湘市| 五台县| 柳河县| 盱眙县| 望江县| 桂东县| 滨海县| 宝清县| 香格里拉县| 新兴县| 周口市| 漾濞| 清丰县| 新绛县| 柳州市| 武山县| 冕宁县| 牟定县| 天气| 上栗县| 阜阳市| 本溪市| 苏州市| 安泽县| 新河县| 安泽县| 兴业县| 定远县| 内黄县| 贺兰县| 博野县| 营口市|