日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

小看--单例设计模式

發(fā)布時(shí)間:2023/12/2 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小看--单例设计模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? (一)單例設(shè)計(jì)描述

? ? ? 只要了解過(guò)設(shè)計(jì)模式的同學(xué)都會(huì)知道:單例設(shè)計(jì)模式,大家都知道單例設(shè)計(jì)模式是一種創(chuàng)建行的設(shè)計(jì)模式。既然是創(chuàng)建型,那么先來(lái)講講,對(duì)象的創(chuàng)建的過(guò)程吧。

? ? ?--靜態(tài)成員:靜態(tài)成員在程序加載的時(shí)候,就會(huì)加載進(jìn)內(nèi)存。

? ? ?--實(shí)例成員:只有new的時(shí)候才有實(shí)例成員。1、為實(shí)例的數(shù)據(jù)字段分配內(nèi)存,然后初始化對(duì)象的附加字段(類(lèi)型指針和同步索引塊),最后調(diào)用類(lèi)型的實(shí)例構(gòu)造器來(lái)設(shè)置對(duì)象的初始化狀態(tài)。

? ? ? 單例模式:一般用在一個(gè)類(lèi)的創(chuàng)建對(duì)象很消耗資源,消耗時(shí)間,并且系統(tǒng)要保證只有一個(gè)對(duì)象的時(shí)候。一句話,對(duì)象的創(chuàng)建并不是很耗時(shí)間,不要刻意去套用單例模式,單例模式必須是在單例的時(shí)候,才單例。

? ? (二)?單例模式的演變

? ? ? ? 下面我們來(lái)模擬實(shí)際情況

public class Singleton {/// <summary>/// 對(duì)象會(huì)持有資源/// </summary>private List<string> _connList=new List<string>(){"測(cè)試數(shù)據(jù)庫(kù)連接","測(cè)試數(shù)據(jù)庫(kù)連接2","測(cè)試數(shù)據(jù)庫(kù)連接3","測(cè)試數(shù)據(jù)庫(kù)連接4"};public Singleton(){long lResult = 0;for (int i = 0; i < 100000; i++){lResult += i;}Thread.Sleep(1000);Console.WriteLine("{0}被構(gòu)造一次",this.GetType().Name);}public void Show(){Console.WriteLine("調(diào)用了Show");}}

? ? ? 這個(gè)類(lèi)的創(chuàng)建需要耗費(fèi)很多資源,里面有個(gè)Show方法。

? ? ? 那么接下來(lái),實(shí)際中,我們可能有十個(gè)地方要用到這個(gè)類(lèi)里面的Show方法,我們的做法是這樣的

//那么接下來(lái),我們這里要調(diào)用十次Show方法for (var i = 0; i < 10; i++) {var singletonObj = new Singleton();singletonObj.Show();}

? ????

?

? ? 這里每次調(diào)用一次,都需要耗費(fèi)很多資源和時(shí)間,這里可能有些同學(xué)就會(huì)說(shuō),那我把這個(gè)singletonObj=new Singleton()提取出來(lái),放到最外面來(lái)。

? ? 那行,按照我們需要,我們把var singletonObj=new Singletone()放到外面,如下所示

? ?

? 貌似這樣就解決了我們的問(wèn)題,但是各位你們想一想,我們一個(gè)系統(tǒng)是有多個(gè)人開(kāi)發(fā)的,A這里這樣做,B可能不知道這里有這個(gè)聲明,那他可能就還是一樣去New Singleton,還是導(dǎo)致我們系統(tǒng)中,存在大量這個(gè)對(duì)象。

? 我們應(yīng)該要如何解決這個(gè)問(wèn)題呢??如何保證這個(gè)對(duì)象在整個(gè)系統(tǒng)只被創(chuàng)建一次呢?

? 單例模式--單線程

? 從上面的問(wèn)題,我們也可以看出因?yàn)檎l(shuí)都可以在New Singleton,所以導(dǎo)致了這個(gè)問(wèn)題。那按照這個(gè)想法,那我們就想啦,那就把構(gòu)造函數(shù)私有化唄,私有化完了之后,我們應(yīng)該還要提供一個(gè)方法或者啥的,給外面調(diào)用(也只能是靜態(tài)的成員),構(gòu)造函數(shù)私有化了,外面是不可以New了的

? ?那就按照,剛剛的說(shuō)法,我們來(lái)進(jìn)行一次改進(jìn)

public class Singleton {/// <summary>/// 對(duì)象會(huì)持有資源/// </summary>private List<string> _connList=new List<string>(){"測(cè)試數(shù)據(jù)庫(kù)連接","測(cè)試數(shù)據(jù)庫(kù)連接2","測(cè)試數(shù)據(jù)庫(kù)連接3","測(cè)試數(shù)據(jù)庫(kù)連接4"};private Singleton(){long lResult = 0;for (int i = 0; i < 100000; i++){lResult += i;}Thread.Sleep(1000);Console.WriteLine("{0}被構(gòu)造一次",this.GetType().Name);}public static Singleton CreateInstance(){return new Singleton();}public void Show(){Console.WriteLine("調(diào)用了Show");}}

? ? 按照我們上面這個(gè)寫(xiě)法,把構(gòu)造函數(shù)私有化了,然后在靜態(tài)方法里面New Singletone();

? ? 調(diào)用結(jié)果如下:

for (var i = 0; i < 10; i++) {var singletonObj = Singleton.CreateInstance();singletonObj.Show();} //寫(xiě)進(jìn)里面去了,是為了模擬有十個(gè)不同的開(kāi)發(fā),再調(diào)用

?

? 那結(jié)果,還是沒(méi)有達(dá)到我們想要的,那現(xiàn)在問(wèn)題就是,對(duì)象沒(méi)有重用,因?yàn)槲覀兠看蝞ew,導(dǎo)致了對(duì)象沒(méi)有做到重用,那就讓對(duì)象進(jìn)行重用唄。最簡(jiǎn)單的方法,就是給一個(gè)靜態(tài)的字段(為啥靜態(tài)呢,因?yàn)槲覀兡沁叿椒ㄊ庆o態(tài)的),然后做一個(gè)判斷,如果對(duì)象為空,那么我們就創(chuàng)建,如果不為空,就不用創(chuàng)建了,如下所示。? ??

? ?

? ?我們?cè)谠瓉?lái)的基礎(chǔ)上,做了如上圖的改進(jìn)。結(jié)果如下,

? ?

? ?我們想要的結(jié)果實(shí)現(xiàn)了,多次調(diào)用的時(shí)候,做了重用對(duì)象,只構(gòu)造了一次。本來(lái)想著單例模式就這樣結(jié)束了(單線程是沒(méi)有問(wèn)題,并且這種實(shí)現(xiàn)是一種懶漢式,懶漢式:當(dāng)你需要用這個(gè)類(lèi)的時(shí)候,才會(huì)去實(shí)例化)。

? ?編程世界里面,我們總是要考慮一下,多線程的情況。

? ?單例模式--多線程

? ?這個(gè)是用Task.Run()開(kāi)啟了也給多線程的異步調(diào)用

for (var i = 0; i < 10; i++){Task.Run(()=>{var singletonObj = Singleton.CreateInstance();singletonObj.Show();}); }Thread.Sleep(5000);

? ?

? ?通過(guò)上面的結(jié)果,我們可以看出,我們的之前的做法,在多線程環(huán)境還是會(huì)調(diào)用多次。

? ?有些同學(xué)就會(huì)說(shuō)用lock鎖啦,行,我們就給他加上一把鎖。

public class Singleton {/// <summary>/// 對(duì)象會(huì)持有資源/// </summary>private List<string> _connList=new List<string>(){"測(cè)試數(shù)據(jù)庫(kù)連接","測(cè)試數(shù)據(jù)庫(kù)連接2","測(cè)試數(shù)據(jù)庫(kù)連接3","測(cè)試數(shù)據(jù)庫(kù)連接4"};private static Singleton singletonObj = null;private static readonly object singleTonObjLock = new object(); //加鎖,之后這里為啥要用readonly,大家可以找private Singleton(){long lResult = 0;for (int i = 0; i < 100000; i++){lResult += i;}Thread.Sleep(1000);Console.WriteLine("{0}被構(gòu)造一次",this.GetType().Name);Console.WriteLine($"線程{Thread.CurrentThread.ManagedThreadId}調(diào)用一次");}public static Singleton CreateInstance(){lock (singleTonObjLock) //很多同學(xué)都說(shuō)用lock this,this肯定是不行的,因?yàn)閘ock是lock引用的,如果這個(gè)this的引用改變了... {if (singletonObj == null){singletonObj = new Singleton();}}return singletonObj;}public void Show(){Console.WriteLine("調(diào)用了Show");}}

? ?看我們給他加完鎖的時(shí)候效果。

? ?

? ?嗯,實(shí)現(xiàn)了我們想要的效果了,說(shuō)明我們加鎖是有效果的。到了這個(gè)時(shí)候,大家可能覺(jué)得一個(gè)單例模式應(yīng)該就快結(jié)束了,那么我們?cè)賮?lái)看看這種情況。

? 單例模式--多線程(雙if+lock)

??

?

?通過(guò)上面的介紹,我們理解了單例模式的演變過(guò)程,也對(duì)單例模式,多線程有了更加深刻的印象。

?(三)單例模式其他實(shí)現(xiàn)

? ? 就像我們一開(kāi)始說(shuō)的那樣,單例模式,其實(shí)一個(gè)進(jìn)程內(nèi),在多線程環(huán)境下,如何保證只有一個(gè)對(duì)象,這就是單例。也可以從這個(gè)定義看出,我們可以通過(guò)靜態(tài)的構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)一個(gè)單例模式。

? ? 靜態(tài)構(gòu)造函數(shù),是由CLR保證的,有且只會(huì)加載一次。

? ? 其他很多方法實(shí)現(xiàn),都是利用static關(guān)鍵字的背后原因,在第一次使用類(lèi)型之前被調(diào)用,且只會(huì)被調(diào)用一次。

? ?(四)懶漢式,餓漢式

? ? ? 懶漢,就是說(shuō)這個(gè)人很懶,需要用的時(shí)候,才構(gòu)建。雙if+lock這種就屬于懶漢式。懶漢式,利用了延遲加載加載的思想。

? ? ? 餓漢:就是調(diào)用我這個(gè)類(lèi)型,就會(huì)幫你創(chuàng)建好;管你用不用,我都會(huì)幫你創(chuàng)建;就是餓了嗎,我后面介紹的利用static關(guān)鍵字的就是屬于餓漢式;餓漢式:管你之前有沒(méi)有(內(nèi)存中),都會(huì)幫你new一個(gè)新的實(shí)例。

? ?(五)單例模式的使用場(chǎng)景

? ? ? ?單例:必須單例才單例,反正沒(méi)必要。單例模式實(shí)現(xiàn)都有性能,損失,靜態(tài)方法。

? ? ? ?單例:會(huì)把對(duì)象常駐內(nèi)存,靜態(tài)的。

? ? ? ?單例的使用,多個(gè)人操作可能會(huì)對(duì)你影響,因?yàn)槎际菍?duì)同一份引用進(jìn)行修改。

? ? ? ?一般用在數(shù)據(jù)庫(kù)連接,打印機(jī),遠(yuǎn)程服務(wù)調(diào)用,等等這些大對(duì)象身上。

 ? //單例模式的應(yīng)用場(chǎng)景補(bǔ)充:讀取配置文件信息,讀取配置文件不應(yīng)該一直new一個(gè)類(lèi),應(yīng)該是單例的。

? ? ? ?

?

? ? ??

?

public class ConfigV1{private static object _lockObj = new object();private static ConfigV1 _instance;private static Dictionary<string,string> _configItems =new Dictionary<string, string>();private ConfigV1(){Init();Console.WriteLine($"{this.GetType().Name}被構(gòu)造一次");}public static ConfigV1 GetInstance(){if (_instance == null){lock (_lockObj){if (_instance == null){_instance=new ConfigV1();}}}return _instance;}public string this[string item]{get{return _configItems[item];}}private void Init(){var config=ConfigurationManager.AppSettings.AllKeys;foreach(var key in config){_configItems.Add(key,ConfigurationManager.AppSettings[key]);}}}

? ? ? ?github:https://github.com/gdoujkzz/DesignPattern.git

  謝謝你閱讀我的博客,如果有收獲,請(qǐng)點(diǎn)一個(gè)贊(推薦)

? ? ?

?

? ?

?

?

?

? ? ?

轉(zhuǎn)載于:https://www.cnblogs.com/gdouzz/p/8319485.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的小看--单例设计模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。