2.单例模块
2.1 知识点
单例模块的作用
减少单例模式重复代码的书写
单例的基本要素
静态实例
私有构造函数
公共访问属性
C#中的泛型单例基类
定义泛型基类:
使用 public class BaseSingletonInCSharp<T>
定义一个泛型基类,其中 T 是泛型参数。
添加泛型约束 where T : class, new()
,确保 T 是引用类型(class)并且具有无参数构造函数(new())。
私有静态字段:
声明一个私有静态字段 private static T instance;
用于存储单例实例。
声明一个私有静态字段 private static readonly object LockObject = new object();
用于线程同步。
公共静态属性 Instance:
声明一个公共静态属性 public static T Instance
用于获取单例实例。
在 get 访问器中实现单例模式的逻辑。
如果 instance 为 null,则进入锁定区域以确保线程安全。
再次检查 instance 是否为 null,以防多个线程同时通过第一个检查。
如果 instance 仍为 null,就在锁定区域内创建一个新的实例并赋值给 instance。
最后,返回单例实例。
受保护的构造函数:
声明一个受保护的构造函数 protected BaseSingletonInCSharp()
,表示该构造函数只能在类内部或派生类中访问。
可以在构造函数中添加初始化代码,但通常不需要,因为实例化是延迟的。
MonoBehaviour中的泛型单例基类
引入Unity引擎的命名空间:
使用 using UnityEngine;
引入Unity引擎的命名空间,以便在代码中使用Unity的类和功能。
声明泛型类 BaseSingletonInMonoBehaviour:
使用 public class BaseSingletonInMonoBehaviour<T> : MonoBehaviour where T : MonoBehaviour
声明一个泛型类 BaseSingletonInMonoBehaviour,它继承自MonoBehaviour。
泛型参数 T 必须是MonoBehaviour的派生类。
私有静态字段:
声明一个私有静态字段 private static T instance;
用于存储单例实例。
公共静态属性 Instance:
声明一个公共静态属性 public static T Instance
用于获取单例实例。
在 get 访问器中实现单例模式的逻辑。
如果 instance 为 null,则尝试在场景中查找具有类型 T 的对象。
如果在场景中找不到该类型的对象,就创建一个新的空游戏对象,向其添加一个类型为 T 的组件,并将其赋值给 instance。
设置游戏对象的名称为类型 T 的名称,并防止在场景切换时销毁这个游戏对象。
最后,返回单例实例。
Awake 虚方法:
Awake 虚方法在对象实例被创建时调用。
如果单例实例尚未创建(即 instance 为 null),则将当前对象实例赋值给 instance。
同样,防止在场景切换时销毁当前对象。
如果单例实例已存在,则销毁当前对象,确保只有一个单例实例存在。
单例测试
测试代码
TestCSharpSingleton.Instance.ShowCSharpInfo();
TestMonoBehaviourSingleton.Instance.ShowMonoBehaviourInfo();
测试结果
2.2 知识点代码
BaseSingletonInCSharp
// 定义一个泛型基类 BaseSingletonInCSharp,要求泛型类型 T 必须是引用类型(class)并且具有无参数构造函数(new())
public class BaseSingletonInCSharp<T> where T : class, new()
{
// 用于存储单例实例的私有静态字段
private static T instance;
// 用于线程同步的锁对象
private static readonly object LockObject = new object();
// 公共静态属性,用于获取单例实例
public static T Instance
{
get
{
// 如果实例尚未创建
if (instance == null)
{
// 使用锁确保线程安全
lock (LockObject)
{
// 再次检查实例是否为空,因为多个线程可能同时通过第一个检查
if (instance == null)
{
// 如果为空,创建一个新的实例并赋值给 instance
instance = new T();
}
}
}
// 返回单例实例
return instance;
}
}
// 受保护的构造函数,只能在类内部或派生类中访问
protected BaseSingletonInCSharp()
{
// 这里可以添加初始化代码,但通常不需要,因为实例化是延迟的
}
}
BaseSingletonInMonoBehaviour
// 引入Unity引擎的命名空间
using UnityEngine;
// 声明一个泛型类 BaseSingletonInMonoBehaviour<T>
// 这个类继承自MonoBehaviour,泛型参数 T 必须是MonoBehaviour的派生类
public class BaseSingletonInMonoBehaviour<T> : MonoBehaviour where T : MonoBehaviour
{
// 静态字段用于存储单例实例
private static T instance;
// 公共静态属性,用于获取单例实例
public static T Instance
{
get
{
// 如果实例尚未创建
if (instance == null)
{
// 尝试在场景中查找具有类型 T 的对象
instance = FindObjectOfType<T>();
// 如果在场景中找不到该类型的对象
if (instance == null)
{
// 创建一个新的空游戏对象
GameObject gameObject = new GameObject();
// 向新创建的游戏对象添加一个类型为 T 的组件,并将其赋值给 instance
instance = gameObject.AddComponent<T>();
// 设置游戏对象的名称为类型 T 的名称
gameObject.name = typeof(T).ToString();
// 不要在场景切换时销毁这个游戏对象
DontDestroyOnLoad(gameObject);
}
}
// 返回单例实例
return instance;
}
}
// Awake 方法在对象实例被创建时调用
protected virtual void Awake()
{
// 如果单例实例尚未创建
if (instance == null)
{
// 将当前对象实例赋值给 instance
instance = this as T;
// 不要在场景切换时销毁该对象
DontDestroyOnLoad(this.gameObject);
}
else
{
// 如果单例实例已存在,则销毁当前对象
Destroy(this);
}
}
}
TestCSharpSingleton
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCSharpSingleton : BaseSingletonInCSharp<TestCSharpSingleton>
{
public void ShowCSharpInfo()
{
Debug.Log($"我是CSharp单例中的{this.GetType().Name}!");
}
}
TestMonoBehaviourSingleton
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestMonoBehaviourSingleton : BaseSingletonInMonoBehaviour<TestMonoBehaviourSingleton>
{
public void ShowMonoBehaviourInfo()
{
Debug.Log($"我是MonoBehaviour单例中的{this.GetType().Name}!");
}
}
Lesson02_单例模块
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson02_单例模块 : MonoBehaviour
{
void Start()
{
TestCSharpSingleton.Instance.ShowCSharpInfo();
TestMonoBehaviourSingleton.Instance.ShowMonoBehaviourInfo();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com