Unity中常用的单例模式
程序员文章站
2024-03-12 19:49:08
...
基本单例
懒汉模式
用到时才创建的单例模式
//单例模式
// 懒汉 在使用时才创建
// 缺点:不适用于多线程
// 私有化构造函数
public class SingletonTest_Base
{
private static SingletonTest_Base instance;
public static SingletonTest_Base Instance
{
get
{
if (instance == null)
{
instance = new SingletonTest_Base();
}
return instance;
}
}
private SingletonTest_Base(){}
}
饿汉模式
初始化时即创建的单例模式
//单例模式
// 饿汉 在编译时创建
// 优点:线程安全
// 缺点:实例常驻 占用内存 不能控制初始化顺序, 大量单例在程序开始时初始化,可能造成卡顿
public class SingletonTest_Inited
{
private static SingletonTest_Inited instance = new SingletonTest_Inited();
public static SingletonTest_Inited Instance
{
get
{
return instance;
}
}
private SingletonTest_Inited(){}
}
线程安全的懒汉模式
加线程锁、二次检查及防止指令重排序
Tip:多核处理器会对运行CPU指令顺序重排优化,MemoryBarrier可以阻止指令重排
//单例模式
// 懒汉
// 加线程锁 线程安全
public class SingletonTest_Lock
{
private static readonly object lockObj = new object();
private static SingletonTest_Lock instance;
private static SingletonTest_Lock Instance
{
get
{
//为空时初始化
if (instance == null)
{
//加锁
lock (lockObj)
{
//再次检查
if (instance == null)
{
var tmp= new SingletonTest_Lock();
// ensures that the instance is well initialized,
// and only then, it assigns the static variable.
//官方文档是说Thread.MemoryBarrier(),
//保证之前的数据存取优先于MemoryBarrier执行,只有在多CPU下才需要使用
System.Threading.Thread.MemoryBarrier();
instance = tmp;
}
}
}
return instance;
}
}
private SingletonTest_Lock(){}
}
范型单例
普通范型单例
范型基类
//单例范型
// 继承自该类的单例,可以通过instance获取实例
// 只有new约束之后才能new,但是new约束的话,继承自该类的子类不能有私有构造函数
// 所以这里的范型单例只是使用上约定的单例,并不能在语法上规定单例
public abstract class Singleton<T> where T : Singleton<T>, new()
{
private static readonly object lockObj = new object();
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new T();
}
}
}
return instance;
}
}
}
单例子类
//子类
public class Manager: Singleton<Manager>
{
// private Manager(){} 继承自new约束的范型,不能私有化构造函数
public void Test() {}
}
调用测试
//调用
public class Client_Test
{
public void Test()
{
//调用测试
Manager.Instance.Test();
//没有被约束的Manager类 可以被new出来新的实例
Manager mgr = new Manager();
}
}
用反射去创建实例的范型单例
范型基类
//用反射去创建实例的单例
public abstract class Singleton_R<T> where T : Singleton_R<T>
{
private static readonly object lockObj = new object();
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
//反射来创建实例
instance = (T) System.Activator.CreateInstance(typeof(T), true);
}
}
}
return instance;
}
}
}
子类
//子类
public class Manager_R: Singleton_R<Manager_R>
{
public void Test() {}
//私有化构造函数
private Manager_R(){}
}
调用
//调用
public class Client_Test_Ref
{
public void Test()
{
Manager_R.Instance.Test();
//构造函数被私有化而不能初始化
// Manager_R mgrr = new Manager_R();
}
}
Mono范型单例
基类
using UnityEngine;
//mono单例
// 只是使用方便
// 通过add依然可以创建出来对象
// 所以并不是语法严谨的单例
public abstract class MonoSingleton<T>: MonoBehaviour where T: MonoSingleton<T>
{
private static object _lock = new object();
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
lock (_lock)
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (instance == null)
{
string instanceName = typeof(T).Name;
GameObject instanceGO = GameObject.Find(instanceName);
if (instanceGO == null)
{
instanceGO = new GameObject(instanceName);
}
instance = instanceGO.AddComponent<T>(); //单例构造函数被私有化了 unity依然可以add
DontDestroyOnLoad(instanceGO); //实例不被释放
}
}
}
}
return instance;
}
}
}
子类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonoSingletonTest: MonoSingleton<MonoSingletonTest>
{
//私有化构造函数
// 这里只是不能被new出来,但依然可以通过unity的addcomponent去创建获取,没有意义
private MonoSingletonTest(){}
public void Test()
{
Debug.Log("test");
}
}
调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonoSingleton_Client : MonoBehaviour
{
void Start ()
{
//调用
MonoSingletonTest.Instance.Test();
//另一个测试
// GameObject 被new出来就会出现在 Hierarchy 面板上
GameObject obj1 = new GameObject("1");
// DontDestroy
GameObject obj2 = new GameObject("2");
DontDestroyOnLoad(obj2);
// 这里会创建出两个
// 一个名为3 另一个名为 3(Clone)
GameObject obj3 = new GameObject("3");
Instantiate(obj3);
}
}
上一篇: iview