本文仅作学习笔记与交流,不作任何商业用途,作者能力有限,如有不足还请斧正
本系列作为七大原则和设计模式的进阶知识,看不懂没关系了解我的专栏C#面向对象与进阶:http://t.csdnimg.cn/mIitr,尤其是关于类的那篇文章即可,另外尤其需要注意的点就是,类的成员属性可以get和set类对象,只是很少这么举例
首先,单例模式可以理解为只有一个外部访问口的类,是在类的概念上设计的
1.单例模式介绍
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来访问这个实例,它在需要控制资源的访问或确保某些操作只执行一次的场景中非常有用
也就是说,单例模式不能在类外部去创建新实例,就是不能"new"
特点
分类
一级分类
根据实例创建的时刻分类,可以理解为一级分类
二级分类
根据优缺点分类,可以理解为建立在一级分类上的二级分类
静态变量初始化:这是饿汉式(Eager Initialization),因为实例在类加载时就已经创建
双重检查锁定:这是懒汉式(Lazy Initialization),因为实例是在第一次需要时才创建,并且通过双重检查锁定来确保线程安全
Lazy<T>:这是懒汉式(Lazy Initialization),因为实例是在第一次需要时才创建,并且使用了 Lazy<T>
类来确保线程安全和延迟加载
2.举栗子
说那么多分类,其实会写会用就行,哪那么多弯弯绕绕的,又不是去考研
静态变量初始化
注意,实例已经在类中被创建,所以叫饿汉=迫不及待需求对象
// 静态变量初始化 A a = A.Instance; a.func(); public class A { //单例模式 //1.私有构造函数 private A() { } //2.私有静态唯一实例 private static A instance = new A(); //3.唯一对外开放的公共属性 public static A Instance => instance; public void func() { Console.WriteLine("这是一个单例模式"); } }
优化方面: 可以设置密封类,并对唯一实例设置为只读状态
sealed
readonly
双重检查锁定
要想实现,懒汉式=对象需要的时候才创建一个,需要objcet的帮忙,其实总的来讲就比静态变量初始化多出一个静态字段和双重锁的逻辑
public class A { //1.私有静态字段 private static A instance = null; //2.私有唯一实例,但是这个实例是objcet的 private static object obj = new object(); //3.私有构造函数 private A() { } //4.唯一对外开放的公共属性 public static A Instance { get { if (instance == null) { lock (obj) { if (instance == null) { instance = new A(); } } } return instance; } } }
Lazy<T>
看到这个大大的T了没有,就是本质上就是泛型类
B b = A<B>.Instance; b.Func(); public class A<T> //where T :new() ()=>new() { //1.私有静态唯一实例 private static Lazy<T> instance = new Lazy<T>(); //2.公共外部属性 public static T Instance => instance.Value; //3.私有构造函数 private A() { } } public class B { public void Func() { Console.WriteLine("单例模式的使用"); } }
Q.为什么是instance.Value而不是instance?
A: 因为泛型T的原因,导致instance像是一个对象盒子,而不是属性Instance需要返回的盒子里面的东西
进阶版本:
public class A<T> where T :new() { //1.私有静态唯一实例 private static Lazy<T> instance = new Lazy<T>(() => new()); //2.公共外部属性 public static T Instance => instance.Value; //3.私有构造函数 private A() { } }