筆記(NS)篇-單例模式(Singleton)
簽名:你存在的價值,取決於能否解決相關的問題。
- 單例模式的特點
- 應用場景
- 代碼演示
- 其他參考寫法
單例模式的特點
1、在某種程度上,單例模式(Singleton)是限制而不是改進類的創建;
2、單例模式可以保證一個類有且只有一個實例;
3、提供一個訪問它的全局訪問點。
應用場景
1、使用Singleton模式有一個必要條件。在一個系統要求一個類只有一個實例時才應當使用單例模式。反過來,如果一個類可以有幾個實例共存,就不要使用單例模式;
2、不要使用單例模式存取全局變量。這違背了單例模式的用意,最好放到對應類的靜態成員中;
3、不要將數據庫連接做成單例,因爲一個系統可能會與數據庫有多個連接,並且在有連接池的情況下,應當儘可能地及時釋放連接。
singleton模式由於使用靜態成員存儲類實例,所以可能會造成資源無法及時釋放,帶來問題。
代碼演示
下面通過Singleton設計模式代碼演示了負載均衡實例對象。在負載均衡模型中,有多臺服務器提供服務,任務分配器隨機挑選一臺服務器提供服務,以確保任務均衡(實際情況比這個複雜的多),這裏,任務分配實例只能有一個,負責挑選服務器並分配任務。程序主要代碼如下:
using System;
using System.Collections;
using System.Threading;
namespace Singleton
{
/// <summary>
/// 負載均衡類
/// </summary>
class LoadBalancer
{
private static LoadBalancer loadBalancer;
private ArrayList ArrayList_Server = new ArrayList();
private Random random = new Random();
protected LoadBalancer() //構造函數
{
ArrayList_Server.Add("Server 1");
ArrayList_Server.Add("Server 2");
ArrayList_Server.Add("Server 3");
ArrayList_Server.Add("Server 4");
}
public static LoadBalancer GetLoadBalancer() //創建實例的唯一入口
{
if (loadBalancer == null) //靜態變量爲空
{
Mutex mutex = new Mutex(); //創建互斥體
mutex.WaitOne(); //防止多用戶併發操作
if (loadBalancer == null)
loadBalancer = new LoadBalancer(); //創建類的實例
mutex.Close(); //關閉互斥體
}
return loadBalancer;
}
public string Server
{
get
{
int r = random.Next(ArrayList_Server.Count);
return ArrayList_Server[r].ToString();
}
}
}
class Program
{
static void Main(string[] args)
{
LoadBalancer b1 = LoadBalancer.GetLoadBalancer(); //創建類的實例
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
LoadBalancer b4 = LoadBalancer.GetLoadBalancer();
if ((b1 == b2) && (b2 == b3) && (b3 == b4)) //判斷實例是否相同
{
Console.WriteLine("同步運行相同的實例對象");
}
Console.WriteLine(b1.Server);
Console.WriteLine(b2.Server);
Console.WriteLine(b3.Server);
Console.WriteLine(b4.Server);
Console.ReadKey();
}
}
}
其他參考寫法
這裏要說的是,關於線程安全問題,除了使用Mutex進行防止併發操作外,還可以使用lock實現。
public class MyCore
{
private static MyCore uniqueInstance;
//定義一個線程同步,使外界不能創建該類實例
private static readonly object locker = new object();
private MyCore()
{
}
public static MyCore GetInstance()
{
if (uniqueInstance == null)
{
lock (locker)
{
if (uniqueInstance == null)
{
uniqueInstance = new MyCore();
}
}
}
return uniqueInstance;
}
}
c#語言的特性決定了c#擁有實現Singleton模式的獨特方法。不詳細解釋,給出一個例子。
public sealed class Singleton
{
Singleton() { } //構造函數
public static Singleton GetInstance()
{
return Nested.instance;
}
class Nested
{
static Nested() { }
internal static readonly Singleton instance = new Singleton();
}
}
這樣雖然代碼很少,但解決了線程性能上的損失。工作原理是,Singleton類被聲明爲sealed,不會用於被繼承,將成員變量Instance聲明爲public readonly,並在聲明時被初始化。通過這些改變,確實得到了Singleton的設計模式,原因是在JIT的處理過程中如果類中的static屬性被任何方法使用時,.NET Framework將對這個屬性進行初始化,於是在初始化Instance屬性的同時Singleton類實例得以創建和裝載。而私有的構造函數和readonly關鍵字保證了singleton不會被再次實例化,這正是singleton設計模式的意圖。