シングルトンパターン基本クラス
外部からのオブジェクトの作成を防ぐためのコンストラクターのプライベート化
外部アクセス用の属性を指定します。この属性は、このクラスの唯一のオブジェクトに相当します。
怠け者モードと腹ペコモードに分かれる
MonoBehavior を継承しないシングルトン モード
public static MyUiManager Instance
{
get
{
if (instance == null)
{
instance = new MyUiManager();
}
return instance;
}
}
MonoBehaviour のシングルトン モードを継承する
public class MyUiManager : MonoBehaviour
{
private MyUiManager() { }
private static MyUiManager instance;
public static MyUiManager Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<MyUiManager>();
}
return instance;
}
}
}
インスタンス = FindObjectOfType<MyUiManager>();
MonoBehaviourを継承したシングルトンはゲームシーンにハングするので、ゲームシーン内で見つけて割り当てる必要があります。
継承と非継承では初期化方法が異なります。
MonoBehaviour の自動シングルトン モードを継承する
if (instance == null)
{
instance = FindObjectOfType<MyUIManager>();
//游戏场景中没有创建物体挂在脚本,写代码来自动做这些事情
if (instance == null)
{
GameObject go = new GameObject("MyUIManager"); //创建游戏对象
instance = go.AddComponent<MyUIManager>(); //挂载脚本到游戏对象身上
}
}
MonoBehaviourを継承したシングルトンモードでのシーン切り替えの問題
if (instance == null)
{
GameObject go = new GameObject("MyUIManager"); //创建游戏对象
instance = go.AddComponent<MyUIManager>(); //挂载脚本到游戏对象身上
}
DontDestroyOnLoad(instance); //让游戏对象切换场景时不销毁
MonoBehavior を継承しないシングルトン モードの基本クラス
/// <summary>
/// 不继承MonoBehaviour 的单例模式基类
/// 作用:继承了这个这个类的类自带单例模式
/// </summary>
public class SingletonPatternBase<T> where T: SingletonPatternBase<T>
{
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
//where 里面要求含有无参构造函数 where T :new()
//....单例怎么能有无参构造函数呢
//instance = new T();
//或者利用反射调用无参构造方法来构造
instance = Activator.CreateInstance(typeof(T), true) as T;
}
return instance;
}
}
//构造方法私有化 private 的话子类也无法继承对象,所以使用protected
protected SingletonPatternBase() { }
}
MonoBehavior を継承するシングルトン モードの基本クラス
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SingletonMonoAutoBase<T> : MonoBehaviour where T:MonoBehaviour
{
protected SingletonMonoAutoBase() { }
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (instance == null)
{
GameObject go = new GameObject(typeof(T).Name); //创建游戏对象
instance = go.AddComponent<T>(); //挂载脚本到游戏对象身上
}
}
return instance;
}
}
}
MonoBehaviour を継承するシングルトン モード基本クラスでのシーン切り替えに関する問題
OnDestroy メソッドでのシングルトン オブジェクトへのアクセスの問題
OnDestroy メソッドが実行されると、リソースがクリアされ、インスタンス検出が空になり、新しいオブジェクトが自動的に生成されるため、エラーが報告されます。
解決:
//シングルトン オブジェクトが存在するかどうかを記録し、OnDestory メソッドでシングルトン オブジェクトにアクセスする際のエラーを防ぐために使用します
public static bool isExisted { get; private set; } = false;
protected virtual void OnDestroy()
{
isExisted = false;
}
マルチスレッドがシングルトンにアクセスするときに発生する問題
オペレーティング システムのスレッド ロックの問題
//线程锁。当多线程访问时,同一时刻只允许一个线程访问
private static object locker = new object();
//volatile关键字修饰的字段,当多个线程都对它进行修改时,可以确保这个字段在任何时刻呈现的都是最新的值
private volatile static T instance;
public static T Instance
{
get
{
if (instance == null)
{
lock(locker)
{
if (instance == null)
{
//或者利用反射调用无参构造方法来构造
instance = Activator.CreateInstance(typeof(T), true) as T;
}
}
}
return instance;
}
}