解读设计模式----单例模式(Singleton Pattern)
??? ? 單例模式可以保證一個類有且只有一個實例,并提供一個訪問它的全局訪問點.在程序設計中,有很多情況需要確保一個類只能有一個實例.從這句話可以看出,Singleton模式的核心:如何控制用戶使用new對一個類的實例構造器的任意調用。如何繞過常規的構造器,提供一種機制來保證一個類只有一個實例?這應該是類設計者的責任,而不是使用者的責任。
?一、單例模式意圖
????? 保證一個類有且只有一個實例,并提供一個訪問它的全局訪問點。
二、單例模式UML圖(該圖來至http://www.dofactory.com/)
?????
三、示例解說單例模式
????? 看看下面這個簡單的示例:
?2{
?3????public?class?Singleton
?4????{
?5????????//靜態私有屬性
?6????????private?static?Singleton?instance;
?7
?8????????///?<summary>
?9????????///?私有構造器--讓類的使用者調用不到此構造器
10????????///?</summary>
11????????private?Singleton()
12????????{?}
13
14????????public?static?Singleton?Instance
15????????{
16????????????get?
17????????????{
18????????????????if?(instance?==?null)
19????????????????{
20????????????????????instance?=?new?Singleton();
21????????????????}
22????????????????return?instance;??//返回的總是第一次實例的對象
23????????????}
24????????}
25????}
26
27????//測試類
28????class?TestSingleton
29????{
30????????public?static?void?Main2(string[]?args)
31????????{
32????????????Singleton?t1?=?Singleton.Instance;
33????????????Singleton?t2?=?Singleton.Instance;
34????????????Console.WriteLine(object.ReferenceEquals(t1,?t2)?==?true);
35????????}
36????}
37}
???? 提供一個靜態的私有屬性,并提供get來實現一個簡單的單例.此外我們還可以通過靜態只讀屬性來實現.看看下面這個MSDN上提供的示例:
?1/**////?<summary>?2///?MSDN上Singleton模式的實現
?3///?</summary>
?4public?class?MsdnSingleton
?5{
?6???//聲明的同時進行初始化
?7???public?static?readonly?MsdnSingleton?Instance?=?new?MsdnSingleton();
?8????????
?9???/**////?<summary>
10???///?私有構造器
11???///?</summary>
12???private?MsdnSingleton()
13???{
14???}
15}
????? 這樣的單例實現的實質等同于提供一個靜態的屬性字段,通過靜態構造器來初始化這個屬性.因為要想訪問靜態字段,那靜態構造器就首先執行,下面是代碼示例:
?1public?class?SameSingleton?2{
?3???//要想訪問靜態字段,那靜態構造器就首先執行
?4???public?static?readonly?SameSingleton?Instance;
?5????????
?6???/**////?<summary>
?7???///?靜態構造器-初始化Instance
?8???///?靜態構造器-完成靜態字段(Instance)的初始化
?9???///?</summary>
10??static?SameSingleton()
11??{
12??????Instance?=?new?SameSingleton();
13??}
14
15??/**////?<summary>
16??///?私有構造器
17??///?</summary
18??private?SameSingleton()
19??{
20?
21??}
22}
????? 上面的實現完全可以達到單例模式的意圖,保證一個類僅且有一個實例,并提供一個全局訪問點.而這在實際應用我們還得注意一點,就是在多線程的調用.于此,我們還得保證線程安全.要保證線程安全其實也是很簡單就可以實現的,只需要通過加鎖和雙重判斷就OK,下面是簡單的多線程的線程安全的實現:
?1using?System;?2using?System.Collections.Generic;
?3using?System.Text;
?4
?5//多線程的Singleton模式實現
?6namespace?DesignPattern.Singleton
?7{
?8????public?class?SingletonMultithread
?9????{
10????????private?static?object?lockHelper?=?new?object();
11
12????????private?static?volatile?SingletonMultithread?instane?=?null;
13????????public?static?SingletonMultithread?Instane
14????????{
15????????????get?
16????????????{
17????????????????if?(instane?==?null)??//雙檢查
18????????????????{
19????????????????????lock?(lockHelper)
20????????????????????{
21????????????????????????if?(instane?==?null)
22????????????????????????{
23????????????????????????????instane?=?new?SingletonMultithread();
24????????????????????????}
25????????????????????}
26????????????????}
27????????????????return?instane;
28????????????}
29????????}
30????????
31
32????????//私有構造方法
33????????private?SingletonMultithread()?
34????????{
35
36????????}
37????}
38
39????class?TestSingletonMultithread
40????{
41????????public?static?void?Main()
42????????{
43????????????SingletonMultithread?s1?=?SingletonMultithread.Instane;
44????????????SingletonMultithread?s2?=?SingletonMultithread.Instane;
45????????????Console.WriteLine(object.ReferenceEquals(s1,?s2)?==?true);
46????????}
47????}
48}
49
其中:private static volatile Singleton instance=null;
--volatile:保證特定平臺的實現必須不要去從新調整指令,保證對象構造的一個非常嚴格的順序。
四、真實項目中的單例
????? 我曾經做過一個網球場的管理系統,客戶要求使用C/S,(隨便PS下客戶,在我做需求的時候建議客戶做B/S系統,管理和部署就很方便,也不用帶上幾百M的.NET Frameworks去裝在客戶電腦上了。可好心討不了客戶的笑顏,他硬說我是在給他做網頁,還說他要的是軟件不是網頁,汗過........),在使用C/S做程序的時候我想大家都遇到過這樣的情況,無論是通過按扭點擊還是菜單來導航,通常我們是像下面這樣實現的:
2{
3????ratForm?rat?=?new?ratForm();
4????rat.MdiParent?=?this;
5????rat.Show();
6
7}
???? 我這里是使用的菜單控件,通過點擊打開新窗體。如果是這樣問題就出現了,每當我們點擊一次菜單上的菜單項就會啟動一個窗體,點幾次就會啟動幾個窗體。見下圖:
????? 這樣顯然是不符合要求的,我們應該做到讓每個窗體只能Show一個出來,這時 單例模式 就能派上用場了。要保證外部不能創建類的實例,才單例中就是通過設置構造方法為私有private,所謂模式可說是一種設計套路,這里我們就依葫蘆畫瓢來畫一次單例,設置構造方法私有,代碼如下;
2{
3????InitializeComponent();
4}
????? 通過一個靜態方法來對完成靜態屬性的初始化;
?1private?static?ratForm?ratf?=?null;?2public?static?ratForm?GetInstance()
?3{
?4???if?(ratf?==?null?||?ratf.IsDisposed)
?5???{
?6??????ratf?=?new?ratForm();
?7??????ratf.MdiParent?=?mainForm.ActiveForm;
?8???}
?9???return?ratf;
10}
???? 通過單例模式的引入,私有了構造方法,并通過一個靜態的方法初始化靜態字段,保證了類的唯一實例,方法GetInstance()就是單例的全局訪問點。這樣設計后就通過GetInstance()方法就得了這個窗體的唯一實例。
1private?void?ratingToolStripMenuItem_Click(object?sender,?EventArgs?e)2{
3????//ratForm?rat?=?new?ratForm();
4????//rat.MdiParent?=?this;
5????//rat.Show();
6????ratForm.GetInstance().Show();
7}
???? 通過單例模式的引入,改善了程序的設計,在窗體調用處只需要通過全局訪問點這個靜態方法就可以得到唯一的實例對象,然后調用其Show()方法,就達到了我們的要求。
五、使用單線程Singleton模式要點
--Singleton模式中的實例構造器可以設置為protected以也許子類派生。
--Singleton模式一般不要支持ICloneable接口,因為這可能導致對個對象實例,與Singleton的意圖違背。
--Singleton模式一般不要支持序列化,因為這也有可能導致多個對象實例,同樣與Singleton模式的意圖違背。
--Singleton模式只考慮到了對象創建的管理,沒有考慮對銷毀的管理。對于自帶垃圾回收的平臺可不考慮這點。
上面總結源于MSDN WebCast
---------------------------------------------------------------------------------------------------------
轉載于:https://www.cnblogs.com/beniao/archive/2008/05/13/1145918.html
總結
以上是生活随笔為你收集整理的解读设计模式----单例模式(Singleton Pattern)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JDBC操作数据库就这八步!
- 下一篇: java 跳跃表_c++实现跳跃表(Sk