網(wǎng)站首頁 編程語言 正文
單例模式也是創(chuàng)建型模式的一種,也是23種設(shè)計(jì)模式中比較簡單的一種。見名思意,在整個(gè)軟件系統(tǒng)中,只有某個(gè)類型的一個(gè)對(duì)象,并且訪問他的地方也只有一個(gè),也就是只有一個(gè)全局對(duì)象訪問點(diǎn),這個(gè)實(shí)例或?qū)ο蟊凰惺菓?yīng)用程序所共享;很多可以使用到這樣的功能模塊:比如數(shù)據(jù)庫連接池對(duì)象、打印機(jī)對(duì)象,因?yàn)檎麄€(gè)系統(tǒng)中,數(shù)據(jù)庫的連接只在一個(gè)地方連接,打印機(jī)在整個(gè)系統(tǒng)中也只有一個(gè)。這種情況下,單例模式就很大的減少了一個(gè)內(nèi)存的開銷,因?yàn)閷?duì)象的創(chuàng)建是比較消耗內(nèi)存的,同時(shí)因?yàn)橄到y(tǒng)中只有一個(gè)實(shí)例,比較容易控制,省去了對(duì)象創(chuàng)建的過程,更快的進(jìn)行一個(gè)響應(yīng),但是在使用單例模式時(shí),由于只有一個(gè)實(shí)例,所有的線程都可以去使用這個(gè)實(shí)例,那么不能保證線程的一個(gè)安全性,如果要想保證線程的安全性,我們需要使用其他的一些輔助措施。所以對(duì)于線程安全的對(duì)象我們最好不要使用單例模式,否則可能會(huì)降低系統(tǒng)的效率。單例模式只需要一個(gè)類就可以實(shí)現(xiàn),自己關(guān)聯(lián)自己,那么如何實(shí)現(xiàn)呢?我們只需要將構(gòu)造方法定義成私有的,這樣用戶就不能自己去創(chuàng)建這個(gè)對(duì)象了,然后通過一個(gè)靜態(tài)方法和靜態(tài)變量來存放類的唯一的一個(gè)實(shí)例。
示例:
創(chuàng)建單例類:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 單例模式 { public class Singleton { ////// 1.定義一個(gè)私有的構(gòu)造函數(shù),在類的外部不能被調(diào)用 /// private Singleton() { Console.WriteLine("我被創(chuàng)建了!"); } // 2.創(chuàng)建該類的一個(gè)靜態(tài)變量 private stati c Singleton Instance; // 3.創(chuàng)建返回值為該類型的一個(gè)靜態(tài)方法 (此方法對(duì)外公開) public static Singleton CreateInstance() { if (Instance == null) { Instance = new Singleton(); } return Instance; } } }
主程序調(diào)用:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 單例模式 { class Program { static void Main(string[] args) { Singleton s1 = Singleton.CreateInstance(); Singleton s2 = Singleton.CreateInstance(); Console.ReadKey(); } } }
運(yùn)行結(jié)果:
從最后的結(jié)果中可以看出,實(shí)例只被創(chuàng)建了一次。
在來看看下面的例子:
for (int i = 0; i < 10; i++) { // 執(zhí)行委托的異步調(diào)用 new Action(() => { Singleton singleton = Singleton.CreateInstance(); }).BeginInvoke(null,null); }
結(jié)果:
從上面的截圖中看出構(gòu)造函數(shù)被執(zhí)行了三次。單例模式不是只會(huì)構(gòu)造一次嗎?這里為什么執(zhí)行了三次呢?因?yàn)檫@里是多線程并發(fā)的,10個(gè)任務(wù)是同時(shí)開始的,可能對(duì)象不為null的時(shí)候有多個(gè)線程進(jìn)入了,所以會(huì)執(zhí)行多次。要解決這種問題,可以使用加鎖。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 單例模式 { public class Singleton { ////// 1.定義一個(gè)私有的構(gòu)造函數(shù),在類的外部不能被調(diào)用 /// private Singleton() { Console.WriteLine("我被創(chuàng)建了!"); } // 2.創(chuàng)建該類的一個(gè)靜態(tài)變量 private static Singleton Instance; // 創(chuàng)建鎖 private static object Singleton_Lock = new object(); // 3.創(chuàng)建返回值為該類型的一個(gè)靜態(tài)方法 (此方法對(duì)外公開) public static Singleton CreateInstance() { lock(Singleton_Lock) // 保證任意時(shí)刻只有一個(gè)線程才能進(jìn)入判斷 { if (Instance == null) { Instance = new Singleton(); } } return Instance; } } }
再次運(yùn)行程序查看結(jié)果:
這時(shí)只會(huì)構(gòu)造一個(gè)對(duì)象了。
在來看看懶漢式的單例模式:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 單例模式 { public class SingletonSecond { private SingletonSecond() { Console.WriteLine("我被創(chuàng)建了!"); } private static SingletonSecond Instance = null; ////// 靜態(tài)構(gòu)造函數(shù):由CLR保證在第一次使用這個(gè)類之前,調(diào)用而且只調(diào)用一次 /// static SingletonSecond() { Instance = new SingletonSecond(); } public static SingletonSecond CreateInstance() { return Instance; } } }
在來看看第三種寫法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 單例模式 { public class SingletonThird { private SingletonThird() { Console.WriteLine("我被創(chuàng)建了!"); } ////// 靜態(tài)變量:會(huì)在類型第一次使用的時(shí)候初始化,而且只初始化一次 /// private static SingletonThird Instance = new SingletonThird(); public static SingletonThird CreateInstance() { return Instance; } } }
代碼下載地址:點(diǎn)擊下載
原文鏈接:https://www.cnblogs.com/dotnet261010/p/7352656.html
相關(guān)推薦
- 2023-11-15 Python pip指定安裝鏡像源;pip安裝如何指定和更改鏡像源?
- 2022-07-16 windows安全加固--關(guān)閉非必要端口
- 2022-12-06 React.memo?和?useMemo?的使用問題小結(jié)_React
- 2023-01-15 解讀keras中的正則化(regularization)問題_python
- 2022-08-05 call(), apply(), bind()有什么區(qū)別?
- 2022-09-15 關(guān)于c++11與c風(fēng)格路徑拼接的速度對(duì)比_C 語言
- 2022-06-13 python語法?之垃圾回收機(jī)制_python
- 2023-07-03 前端面試中遇到的垂直居中問題
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支