c#中單例類與靜態(tài)類的區(qū)別以及使用場(chǎng)景
前言
哈哈,我來了,我又來了,在這年關(guān)將至的時(shí)候,趁有時(shí)間,就多學(xué)習(xí)和溫習(xí)點(diǎn)老的知識(shí)。我們?cè)?net core開發(fā)中,會(huì)經(jīng)常使用注入來注入一個(gè)單例類,而在沒有注入的時(shí)候,大部分情況會(huì)自己實(shí)現(xiàn)一個(gè)單例類,或者更簡(jiǎn)單的就是實(shí)現(xiàn)一個(gè)靜態(tài)類。而常常在使用中,都能完成特定的目的,然而它們間的區(qū)別是什么呢?
1.設(shè)計(jì)模式:單例模式
單例模式:屬于設(shè)計(jì)模式中創(chuàng)建類型的模式,通過單例模式的方法創(chuàng)建的類,在當(dāng)前程序中只有一個(gè)實(shí)例,當(dāng)然可以實(shí)現(xiàn)為線程安全的單例。
這里簡(jiǎn)單復(fù)習(xí)下創(chuàng)建代碼:
1.1 使用時(shí)分配,
使用時(shí)實(shí)例化,多線程應(yīng)用時(shí),使用不當(dāng)會(huì)有線程安全問題。
public class SingletonA { //私有成員,使用時(shí)分配內(nèi)存 private static SingletonA _instance = null; //私有構(gòu)造,杜絕直接new類 private SingletonA() { } //獲取實(shí)例 public static SingletonA GetInstance () { if (_instance == null) { _instance = new SingletonA(); } return _instance; } }
1.2 聲明時(shí)實(shí)例化
聲明實(shí)例時(shí)實(shí)例化,多線程應(yīng)用時(shí),使用不當(dāng)會(huì)有線程安全問題。
public class SingletonB { //私有靜態(tài)成員,聲明類實(shí)例時(shí),分配 private static readonly SingletonB _instance = new SingletonB(); //私有構(gòu)造,杜絕直接new類 private SingletonB() { } public static SingletonB GetInstance() { return _instance; } }
1.3 雙檢鎖
推薦這個(gè),經(jīng)典的線程安全單例實(shí)現(xiàn)
public class SingletonD { private static SingletonD _instance = null; private static readonly object _lockObject = new object(); private SingletonD() { } public static SingletonD GetInstance() { if (_instance == null) { lock (_lockObject) { if (_instance == null) _instance = new SingletonD(); } } return _instance; } }
1.4 .net 特性保證的線程安全
最精簡(jiǎn)版
public sealed class SingletonC { private SingletonC() { } public static readonly SingletonC Instance = new SingletonC(); }
1.5 使用DI依賴注入時(shí)的實(shí)現(xiàn)
//FileLogger只需要定義成一般的類即可,無需按照單例模式進(jìn)行實(shí)現(xiàn),當(dāng)然也不能是靜態(tài)類。 public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddSingleton<ILogger, FileLogger>(); }
2. 單例類和靜態(tài)類的比較
我們基于以下幾個(gè)要點(diǎn)進(jìn)行比較
- 是否支持依賴注入
- 內(nèi)存管理是怎樣的
- 可擴(kuò)展性
- 可測(cè)試性
靜態(tài)類形如:
public static class StaticExample { private static readonly object lockObj = new object(); public static void Log(string message) { //Write code here to log data. } }
特性比較 | 靜態(tài)類 | 單例類 |
---|---|---|
是否支持依賴注入 | 否,編譯時(shí)提示靜態(tài)類型不能作為類型參數(shù) | 支持 |
內(nèi)存管理是怎樣的 | 靜態(tài)類存儲(chǔ)在托管堆的high frequency heap,僅當(dāng)應(yīng)用程序卸載時(shí),才釋放內(nèi)存 | 單例類的單個(gè)實(shí)例是靜態(tài)的,因此也保存在high frequency heap,當(dāng)應(yīng)用程序卸載時(shí),才釋放內(nèi)存。但是,與只能具有靜態(tài)對(duì)象的靜態(tài)類不同,單例類可以同時(shí)具有靜態(tài)和非靜態(tài)對(duì)象。因此,從內(nèi)存管理的角度來看,當(dāng)您使用單例類時(shí),可以利用垃圾回收管理對(duì)象。 |
可擴(kuò)展性 | 您不能繼承靜態(tài)類并覆蓋其方法 ;靜態(tài)類不能具有擴(kuò)展方法 | 單例類通常包含一個(gè)私有構(gòu)造函數(shù),并標(biāo)記為已密封,以指示它既不能實(shí)例化也不能繼承;因此,只有在單例類中具有非私有構(gòu)造函數(shù)的情況下,才可以擴(kuò)展單例類;單例類可以具有擴(kuò)展方法 |
可測(cè)試性 | 模擬靜態(tài)類非常困難,特別是在包含靜態(tài)對(duì)象的時(shí)候。當(dāng)然如果是只有靜態(tài)方法,且冪等則還是很容易測(cè)試的 | 測(cè)試單例類很容易 |
3.使用場(chǎng)景
經(jīng)過上面的對(duì)比,你應(yīng)該看出端倪了。
當(dāng)您只需要一個(gè)包含多個(gè)方法的工具類時(shí),靜態(tài)類是一個(gè)不錯(cuò)的選擇,在這種情況下您不需要實(shí)例。因?yàn)槟鷽]有此類的任何實(shí)例,所以這個(gè)簡(jiǎn)單的實(shí)現(xiàn)提高了應(yīng)用程序的性能。
單例模式可用于設(shè)計(jì)只需要一個(gè)實(shí)例的類。典型示例包括用于日志記錄,緩存,線程池等的管理器類,在這些場(chǎng)景,單例類是一個(gè)不錯(cuò)的選擇。為此,您應(yīng)該有一個(gè)實(shí)例,以避免對(duì)同一資源的請(qǐng)求沖突。
還有在引入了DI框架后,你應(yīng)該多多使用單例類,因?yàn)閷?shí)現(xiàn)這樣的需求,就是簡(jiǎn)單的定義一個(gè)普通的類,然后注冊(cè)到DI中即可。
當(dāng)然還有一點(diǎn)就是單例類更加像面向?qū)ο缶幊?,哈哈~~~
總結(jié)
到此這篇關(guān)于c#中單例類與靜態(tài)類的區(qū)別以及使用場(chǎng)景的文章就介紹到這了,更多相關(guān)c#單例類與靜態(tài)類的區(qū)別及使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用DevExpress中的XtraCharts控件實(shí)現(xiàn)圖表
這篇文章介紹了C#使用DevExpress中的XtraCharts控件實(shí)現(xiàn)圖表的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05基于WPF實(shí)現(xiàn)PDF的顯示與轉(zhuǎn)換
這篇文章為大家詳細(xì)主要介紹了如何基于WPF實(shí)現(xiàn)PDF的顯示并轉(zhuǎn)換成圖片,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12Unity實(shí)現(xiàn)UI光暈效果(發(fā)光效果)
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)UI光暈效果,發(fā)光效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01C#獲取存儲(chǔ)過程返回值和輸出參數(shù)值的方法
這篇文章主要介紹了C#獲取存儲(chǔ)過程返回值和輸出參數(shù)值的方法,有需要的朋友可以參考一下2014-01-01ItemsControl 數(shù)據(jù)綁定的兩種方式
這篇文章主要介紹了ItemsControl 數(shù)據(jù)綁定的兩種方式,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03淺談Visual Studio 2019 Vue項(xiàng)目的目錄結(jié)構(gòu)
這篇文章主要介紹了Visual Studio 2019 Vue項(xiàng)目 目錄結(jié)構(gòu),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03C#實(shí)現(xiàn)合并多張圖片為GIF動(dòng)態(tài)圖
這篇文章主要為大家詳細(xì)介紹了C#如何將把一張又一張的圖片去拼合成一張GIF動(dòng)態(tài)圖片,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-12-12