目标
保证进程中,某个类只有一个实例。
懒汉式
一、私有构造函数
把对象创建的权限关闭,对外提供一个公开的静态方法,起到对象重用的效果。
如果我们讲一个类的构造函数私有化,那么在外部就不能构造实例了
public class Student
{
private Student()
{
Console.WriteLine("调用了一次构造函数");
}
}
二、创建全局唯一静态变量
private static volatile Student student = null;
volatile
关键字是促进线程安全的,这里不是重点,感兴趣可以百度
三、公开的静态方法提供对象实例
public static Student CreateInstance()
{
//如果student == null 则返回new Student()
return student ?? new Student();
}
这种方式,只有在我们调用了该方法才会去构造,所以叫做懒汉式
四、加锁
上诉方法中如果我们在多线程中同时创建新实例的话,结果就不是一个了
for (int i = 0; i < 5; i++)
{
Task.Run(() =>
{
Student student = Student.CreateInstance();
});
}
结果如下,构造函数被调用了5次
所以我们应该双if
加锁,避免同时创建,也提高效率
private static object Singleton_Lock = new object(); //单例锁
public static Student CreateInstance()
{
//如果student == null 则返回new Student()
if (student == null)
{
lock (Singleton_Lock)
{
if (student == null)
{
student = new Student();
}
}
}
return student;
}
饿汉式
饿汉式使用的是静态构造函数
,他是由CLR
保证的,在程序第一次使用这个类型前被调用,且只调用一次
前两步与懒汉式
相同。
三、静态构造函数
static Student()
{
student = new Student();
}
四、修改CreateInstance方法
public static Student CreateInstance()
{
return student;
}
可以看到,相对于懒汉式
,饿汉式
无论你调不调用CreateInstance
方法,改实例都会被创建。
饿汉式2
饿汉式还有一种方式是使用的静态字段
,他也是由CLR
保证的,在程序第一次使用这个类型前被初始化且只有一次。另外静态字段
比静态构造函数
时间还要早。
静态字段
private static Student student = new Student();
其他与上相同。