动机:
在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例,这应该是类设计者的责任,而不是使用者的责任。
意图:
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
—— 《设计模式》GoF
代码说明:
Singleton_SingleThread.cs //单线程实现
Singleton.cs 和 Singleton_MultiThread.cs //多线程支持(Singleton.cs是C#的实现方法)
Test.cs //测试类
using System.Collections.Generic;
using System.Text;
namespace _1___Singleton
{
public class Singleton_SingleThread
{
private Singleton_SingleThread() { } //私有构造器
private static Singleton_SingleThread instance; //私有静态字段
public static Singleton_SingleThread Instance //只读属性
{
get
{
if (instance == null)
{
instance = new Singleton_SingleThread();
}
return instance;
}
}
}
}
//Singleton.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace _1___Singleton
{
class Singleton
{
public static readonly Singleton Instance = new Singleton();
private Singleton() { }
}
//class Singleton和class Singleton的意义一样
//class Singleton展开后的形式如下类:
//class Singleton
//{
// public static readonly Singleton Instance;
// static Singleton()
// {
// Instance = new Singleton();
// }
// private Singleton();
//}
}
//Singleton_MultiThread.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace _1___Singleton
{
class Singleton_MultiThread
{
private Singleton_MultiThread() { } //私有构造器
private static object lockHelper = new object();
//声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。
//这样可以确保该字段在任何时间呈现的都是最新的值。
private static volatile Singleton_MultiThread instance = null;
public static Singleton_MultiThread Instance //只读属性
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)
{
instance = new Singleton_MultiThread();
}
}
}
return instance;
}
}
}
}
//Test.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace _1___Singleton
{
class Test
{
Singleton_MultiThread s1, s2;
void CreateSingletonInstance1()
{
s1 = Singleton_MultiThread.Instance;
}
void CreateSingletonInstance2()
{
s2 = Singleton_MultiThread.Instance;
}
public static void Main()
{
测试Singleton_SingleThread
//Singleton_SingleThread s1 = Singleton_SingleThread.Instance;
//Singleton_SingleThread s2 = Singleton_SingleThread.Instance;
//Console.WriteLine(Object.ReferenceEquals(s1, s2));//output:True
//Console.Read();
//测试Singleton_MultiThread
Test test = new Test();
Thread t1 = new Thread(new ThreadStart(test.CreateSingletonInstance1));
Thread t2 = new Thread(new ThreadStart(test.CreateSingletonInstance2));
t1.Start();
t2.Start();
Thread.Sleep(1000);
Console.WriteLine(object.ReferenceEquals(test.s1, test.s2));
Console.Read();
}
}
}