单例模式中,实现方式有以下几种,自己简单地总结了一下。其中,通过一次判空(只适用于单线程环境)和一次判空加锁(多线程,但效率不高),这两种方法就不多说了,下面只陈述改良之后的方法:
方法一:通过加锁,两次判空实现单例模式
public sealed class SingleTon1
//由sealed修饰的类或方法将不能被继承或是重写。
{
private SingleTon1() { }
private static readonly object MyLock = new object();
private static SingleTon1 instance = null;
public static SingleTon1 GetInstance()
{
//第一次判断省去加锁的过程消耗
if (instance == null)
{
//多线程中保证只有一个线程能够创建实例
lock (MyLock)
{
//加锁过程也是多线程,所以需要再次判断
if (instance == null)
{
instance = new SingleTon1();
}
}
}
return instance;
}
}
这里解释一下private SingleTon1() { } 构造函数私有化,外部类不可以new它,但是需要写一个方法将自己new的return 出去,如方法getInstance()。
单例模式有以下特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
看好第三点的,必须,必须给其他对象提供,否则就不能称之为单例了。
单例模式保证了全局对象的唯一性,避免了一次创建多个对象
方法二:借助C#独有的特性,利用静态变量实现单例模式
public sealed class SingleTon2
{
private SingleTon2() { }
private static readonly SingleTon2 Instance = new SingleTon2();
public static SingleTon2 GetInstance()
{
return Instance;
}
}
如果没有在类中写构造函数,那么框架会为我们生成一个构造函数,那么如果我们在类中定义了静态变量,但是又没有定义静态构造函数,那么框架也会帮助我们来生成一个静态构造函数来让框架自身来调用。
方法三:利用静态构造函数实现,与方法二同理
public sealed class SingleTon3
{
private SingleTon3() { }
private static readonly SingleTon3 Instance = null;
static SingleTon3()
{
Instance = new SingleTon3();
}
public static SingleTon3 GetInstance()
{
return Instance;
}
}
静态构造函数只执行一次,在静态构造函数中初始化静态变量,这样就保证了只初始化一次实例。但是,只要第一次用到Singleton3的时候就会执行静态构造函数,如果不需要创建实例,就会白白浪费资源,于是,下面的方法
方法四:按需创建实例
public sealed class SingleTon4
{
private SingleTon4() { }
public static SingleTon4 GetInstance()
{
return Nested.Instance;
}
//创建一个嵌套类
class Nested
{
internal static readonly SingleTon4 Instance = null;
static Nested()
{
Instance = new SingleTon4();
}
}
}
类型Nested只有在调用SingleTon4 GetInstance()的时候才用到,由于其私有属性,他人无法使用Nested类型。因此,当我们第一次通过GetInstance()得到SingleTon4的实例时,会自动调用Nested的静态构造函数来创建实例Instance;如果我们不调用方法GetInstance()就不会触发.NET运行时调用Nested,也就不会创建实例,真正实现了按需创建。