一、定义
一个类只存在一个实例,并且该实例由单例类自己创建。
二、特点
- 只有一个实例
- 必须由单例类自己创建实例
- 必须提供一个全局访问点
三、结构
- 单例类:包含一个实例并可以自己创建实例的类
- 访问类:使用单例的类
四、实现
1、实现
(1) 单例类构造函数私有化
(2)定义全局私有变量,类型为单例类
(3)定义全局访问访问方法,方法中创建单例类的实例
2、模式
(1)线程安全
- 饿汉式:单例类在程序加载的时候就已经创建了实例,访问类可以直接调用
- 加锁机制:利用双重判断加锁的方式保证单线程创建实例。
(2)非线程安全
- 懒汉式:单线程中,第一次调用的时候会创建实例
五、代码示例
1、饿汉式
/// <summary>
/// 线程安全单例模式
/// </summary>
public class Singleton
{
/// <summary>
/// 饿汉式单例:类加载的时候就创建实例
/// </summary>
private static readonly Singleton instance = new Singleton();
//构造函数私有化
private Singleton(){}
/// <summary>
/// 获取实例
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
return instance;
}
}
2、懒汉式
/// <summary>
/// 非线程安全单例模式
/// </summary>
internal class Singleton1
{
/// <summary>
/// 懒汉式单例
/// </summary>
private static Singleton1 instance;
/// <summary>
/// 构造函数私有化
/// </summary>
private Singleton1() { }
/// <summary>
/// 获取实例
/// </summary>
/// <returns></returns>
public static Singleton1 GetInstance()
{
if (instance == null)
{
instance = new Singleton1();
}
return instance;
}
}
3、加锁
/// <summary>
/// 线程安全单例:双重判断+加锁
/// </summary>
internal class Singleton2
{
/// <summary>
/// 全局锁
/// </summary>
private static object locker = new object();
/// <summary>
/// 全局变量
/// </summary>
private static Singleton2 instance;
/// <summary>
/// 构造函数私有化
/// </summary>
private Singleton2() { }
/// <summary>
/// 获取实例接口
/// </summary>
/// <returns></returns>
public static Singleton2 GetInstance()
{
if (instance == null)
{
lock (locker)
{
if (instance == null)
{
instance = new Singleton2();
}
}
}
return instance;
}
}
调用
static void Main(string[] args)
{
{
//饿汉式单例
Singleton singleton = Singleton.GetInstance();
//线程安全
for (int i = 0; i < 5; i++)
{
Task.Run(() =>
{
Singleton singleton = Singleton.GetInstance();
});
}
}
{
//懒汉式单例
Singleton1 singleton = Singleton1.GetInstance();
//非线程安全
for (int i = 0; i < 5; i++)
{
Task.Run(() =>
{
Singleton1 singleton = Singleton1.GetInstance();
});
}
}
{
Singleton2 singleton = Singleton2.GetInstance();
//线程安全单例
for (int i = 0; i < 5; i++)
{
Task.Run(() =>
{
Singleton2 singleton = Singleton2.GetInstance();
});
}
}
}
六、优缺点
1、优点
- 内存中只有一个实例,节约内存资源
- 可以在系统中全局共享该单例资源
2、缺点
扩展性差