目录
有时候需要在程序中保证一个类只能有一个实例,并且提供一个该实例的全局访问点,这时候就需要利用单件模式。所有的代码是在控制台应用中可以运行的。
单线程
静态属性
用静态属性和私有构造器来实现单例模式,静态属性确保全局只有一个实例,私有构造器确保外部无法构造该类实例,通过对静态属性的第一次访问,创建该类的一个实例,以后所有的对属性的访问都是对该实例的访问。
静态构造器
class Singleton
{
public static readonly Singleton Instance = new Singleton();
private Singleton()
{
}
}
静态构造器不仅支持单线程,也支持多线程。上述字段初始化方式称为内联初始化,等效于下述代码。
class Singleton
{
public static readonly Singleton Instance;
static Singleton()
{
Instance = new Singleton();
}
private Singleton()
{
}
}
多线程
多线程情况下,假设线程1和2同时第一次访问Singleton.Instance,那么线程1就会新建一个实例,与此同时,线程2也会新建一个实例,因此,为了确保线程安全,我们需要设置线程同步锁。这里,设置双重保障,用volatile关键字保证编译器在编译过程中不会对代码进行调整,同步锁lockHelper保证不会有两个线程同时访问instance字段。
class Singleton
{
private static volatile Singleton instance;
private static object lockHelper = new object();
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
private Singleton()
{
}
}
测试
这里测试一下是否实现我们的单例模式,Object.GetType()函数返回的是类名称,为了比较两个实例是否相同,需要用到反射,具体来说使用System.Object.ReferenceEquals函数,具体代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SingletonMode
{
class Program
{
static void Main(string[] args)
{
Singleton t1 = Singleton.Instance;
Singleton t2 = Singleton.Instance;
Console.WriteLine("t1和t2类型" + t1.GetType().ToString());
Console.Write("t1和t2类型是否相等:");
Console.WriteLine(t1.GetType() == t2.GetType());
Console.Write("t1和t2实例是否相等:");
Console.WriteLine(System.Object.ReferenceEquals(t1, t2));
Console.WriteLine("\n");
Student s1 = new Student();
Student s2 = new Student();
Console.WriteLine("s1和s2类型" + s1.GetType().ToString());
Console.Write("s1和s2类型是否相等:");
Console.WriteLine(s1.GetType() == s2.GetType());
Console.Write("s1和s2实例是否相等:");
Console.WriteLine(System.Object.ReferenceEquals(s1, s2));
Console.ReadKey();
}
}
}
class Singleton
{
public static readonly Singleton Instance;
static Singleton()
{
Instance = new Singleton();
}
private Singleton()
{
}
}
class Student
{
}
代码输出结果
t1和t2类型Singleton
t1和t2类型是否相等:True
t1和t2实例是否相等:True
s1和s2类型Student
s1和s2类型是否相等:True
s1和s2实例是否相等:False