单例模式:通过单例模式的方法创建的类在当前进程中只有一个实例
要求:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
属于
创建型(Creational)模式:负责对象创建,我们使用这个模式,就是为了创建我们需要的对象实例的。
其他:
结构型(Structural)模式:处理类与对象间的组合
行为型(Behavioral)模式:类与对象交互中的职责分
单例模式 实际场景:
/// <summary> /// 定义一个天气类 /// </summary> public class WeatherForecast { public WeatherForecast() { Date = DateTime.Now; } public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } }
[HttpGet] public WeatherForecast Get() { // 实例化一个对象实例 WeatherForecast weather = new WeatherForecast(); return weather; }
演变一:定义一个静态变量来保存类的唯一实例
定义私有构造函数,使外界不能创建该类实例
/// <summary> /// 定义一个天气类 /// </summary> public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义私有构造函数,使外界不能创建该类实例 private WeatherForecast() { Date = DateTime.Now; } /// <summary> /// 静态方法,来返回唯一实例 /// 如果存在,则返回 /// </summary> /// <returns></returns> public static WeatherForecast GetInstance() { // 如果类的实例不存在则创建,否则直接返回 // 其实严格意义上来说,这个不属于【单例】 if (uniqueInstance == null) { uniqueInstance = new WeatherForecast(); } return uniqueInstance; } public DateTime Date { get; set; }public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } }
缺点:多线程情况下会走两边构造函数,即生成多个类 ,要解决多线程情况下唯一就要加锁
// 定义一个锁,防止多线程 private static readonly object locker = new object();
public static WeatherForecast GetInstance() { // 当第一个线程执行的时候,会对locker对象 "加锁", // 当其他线程执行的时候,会等待 locker 执行完解锁 lock (locker) { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new WeatherForecast(); } } return uniqueInstance; }
这样就还有一点点问题:创建对象了之后就只用管对象是不是为空 不用判断是否加锁了 因为有了对象就不用再创建了
public static WeatherForecast GetInstance()
{
// 当第一个线程执行的时候,会对locker对象 "加锁",
// 当其他线程执行的时候,会等待 locker 执行完解锁
if (uniqueInstance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new WeatherForecast();
}
}
}
return uniqueInstance;
}
那么singleton是不是单例呢
/ 单例注册到容器内 services.AddSingleton<Feeling>(); 结论:Singleton是一种单例,而且还是双检锁那种, 因为结论可以看出,我们使用单例模式,直接可以使用依赖注入 Sigleton 就能满足的,很方便
原文:https://www.cnblogs.com/laozhang-is-phi/p/Singleton-Pattern.html