一个类只有一个实例,并且提供了一个全局的访问点.
要求:一个类只有一个实例,并且提供了一个全局的访问点。注意:客户端在调用一个类的时候,不会考虑这个类是否只能有一个实例等问题的,所以这是设计者的问题。
实现:
实现1
public sealed class Singleton
{
private int count = 0;
//to make sure that all the instance of the class Singleton share the variable instance
static Singleton instance = null;
//private constructor to make sure that the client can't create the instance of the class singleton by calling the constructor
Singleton()
{
count++;
}
//the property Instance to provide an unique access point to get the unique instance of the class Singleton
public static Singleton Instance
{
get
{
if( instance == null )
{
instance = new Singleton();
}
return instance;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
缺点:
对于线程来说并不安全,因为在多线程的环境下有可能得到Singleton类的多个实例.当两个线程都在判断时,因为内存模型并不能保证对象实例在第二个线程创建之前被发现.
优点:
由于实例是在Instance属性方法内部创建的,因此类阿宽衣使用附加功能,因此类可以使用附加功能,比如对其他成员进行初始化等
直到对象要求产生一个实例才执行实例化,这种方法称为"情性实例化",情性实例化避免了在应用程序启动时实例化不必要的
singleton.
实现2:
public sealed class Singleton_Thread
{
static Singleton_Thread instance = null;
static readonly object padlock = new object();
static int count = 0;
Singleton_Thread()
{
count++;
}
public static Singleton_Thread Instance
{
get
{
//using the lock to make sure that at the same time only one thread can get into the block int the {}
lock(padlock)
{
if(instance == null)
{
instance = new Singleton_Thread();
}
return instance;
}
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
优点: 用lock讲创建实例的代码同一时刻只能被一个线程访问,实现了线程安全,但是每次创建都要加锁则增加了额外的开销
实现3:使用双锁
public sealed class Singleton_DoubleLock
{
static Singleton_DoubleLock instance = null;
static int count = 0;
static readonly object padlock = new object();
Singleton_DoubleLock()
{
count++;
}
public static Singleton_DoubleLock Instance
{
get
{
if( instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton_DoubleLock();
}
}
}
return instance;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
优点:解决线程并发,同时避免每个Instance属性的调用都出现独占锁定.
并且将实例化延迟到第一次访问对象时发生
缺点:不能实现延迟初始化
实现4:使用静态构造函数
public sealed class Singleton_Static
{
//static表明是在静态初始化的时候被初始化.这个初始化操作由公用语言运行库完成
static readonly Singleton_Static instance;
static int count;
static Singleton_Static()
{
instance = new Singleton_Static();
count++;
}
Singleton_Static()
{
}
public static Singleton_Static Instance
{
get
{
return instance;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
和上面的区别: 由CLR实现变量初始化
实现5:延迟初始化
public sealed class Singleton_Initil
{
static int count;
Singleton_Initil()
{
count++;
}
public static Singleton_Initil Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
internal static readonly Singleton_Initil instance = new Singleton_Initil();
};
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
应用例子:
简单计数器,四个线程同时进行计数.
//实现一个单个计数器,singleton设计模式,所以只有一个计数器供四个线程使用.
public class CountSingleton
{
static CountSingleton uniCounter = new CountSingleton();
private int totNum = 0;
private CountSingleton()
{
Thread.Sleep(2000);
}
public static CountSingleton Instance()
{
return uniCounter;
}
public void Add()
{
totNum++;
}
public int GetCounter()
{
return totNum;
}
};
public class CountMutiThread
{
public CountMutiThread()
{
}
//每个线程执行的操作就是进行计数,并输出当前的计数值
public static void DoSomeWork()
{
string results = "";
CountSingleton MyCounter = CountSingleton.Instance();
for(int i = 1; i
{
MyCounter.Add();
results += "线程";
results += Thread.CurrentThread.Name.ToString() + "--> ";
results += "当前的计数";
results += MyCounter.GetCounter().ToString();
results += "\n";
Console.WriteLine(results);
results = "";
}
}
//创建四个线程并开始运行
public void StartMain()
{
Thread thread0 = Thread.CurrentThread;
thread0.Name = "Thread 0";
Thread thread1 = new Thread(new ThreadStart(DoSomeWork));
thread1.Name = "Thread 1";
Thread thread2 = new Thread(new ThreadStart(DoSomeWork));
thread2.Name = "Thread 2";
Thread thread3 = new Thread(new ThreadStart(DoSomeWork));
thread3.Name = "Thread 3";
thread1.Start();
thread2.Start();
DoSomeWork();
thread3.Start();
}
};
class CountClient
{
static void Main(string[] args)
{
CountMutiThread cmt = new CountMutiThread();
cmt.StartMain();
Console.ReadLine();
}
}