设计模式学习笔记-单例模式
概述:
单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象,一个最好的办法就是,让这个类自身保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问改实例的方法。
适用场合:
1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
类图:
代码示例:
class Singleton
{
private static Singleton instance;
//构造方法让它私有化,这样外界就不能通过 new 来实例化了
private Singleton()
{}
public static Singleton GetInstance()
{
if(null==instance)
{
instance = new Singleton();
}
return instance;
}
}
前台调用测试
static void Main(string[] args)
{
Singleton s1= Singleton.GetInstance();
Singleton s2=Singleton.GetInstance();
if(s1==s2)
{
Console.Write("相同的实例");
}
Console.Read();
}
多线程下的单例:多个线程同时调用GetInstance()方法,会有可能创建多个实例的。可以通过lock语句来处理,确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,将会被阻塞一直等待对象资源被释放。
class SingletonThreads
{
private static SingletonThreads instance;
//程序运行时创建一个静态制度的进程辅助对象
private static readonly object syncRoot = new object();
private SingletonThreads() { }
/// <summary>
/// 双重锁定判断
/// </summary>
/// <returns></returns>
public static SingletonThreads GetInstance()
{
//如果不判断是否被实例化,每次都要执行枷锁,判断后只在没有被实例化的时候才枷锁,提高了性能
if (instance == null)
{
//在同一个时刻加了锁的那部分程序只有一个线程可以进入
lock (syncRoot)
{
if (instance == null)
{
instance = new SingletonThreads();
}
}
}
return instance;
}
}
C# 的这种静态初始化方法,解决了多线程下的线程安全问题,这样就不用通过双重枷锁机制来解决
线程安全问题了,但是类一加载就实例化,提前占用系统资源,通过枷锁机制可以不用提前
占用系统资源,根据实际情况来选择单例模式的实现方法
/// <summary>
/// 密封类,阻止派生,防止通过派生增加实例
/// </summary>
public sealed class SingletonSealed
{
//readonly 表示静态初始化 ,第一次调用此类时,CLR 负责处理变量初始化
private static readonly SingletonSealed instance = new SingletonSealed();
private SingletonSealed() { }
public static SingletonSealed GetInstance()
{
return instance;
}
}
小结:
单例模式应用太广泛了,例如实例化数据库访问类,文件读写类