Unity 开发过程中感觉用到的最频繁的应该就是单例模式,它能够帮助调用全局变量,方便使用。也可以作为基本的框架管理器来使用,比如在 “Unity项目架构设计与开发管理” 中介绍的 Manager Of Managers 的使用就是利用单例模式,来集中管理某一项功能。为了方便不重复编写单例脚本(其实就是懒😒),基于基类可以继承的特性写了一个泛型基类,可以通过继承来实现单例。

0×00 Wiki 介绍

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用 getInstance 这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。

单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。

0×01 Unity 中单例模式泛型基类实现

using UnityEngine;
​
/// <summary>
/// 单例基类
/// </summary>
/// <typeparam name="T">类名</typeparam>
public class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    private static T instance = null;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType(typeof(T)) as T;
                if (instance == null)
                {
                    instance = new GameObject("_" + typeof(T).Name).AddComponent<T>();
                    DontDestroyOnLoad(instance);
                }
                if (instance == null)
                    Debug.Log("Failed to create instance of " + typeof(T).FullName + ".");
            }
            return instance;
        }
    }
​
    void OnApplicationQuit() { if (instance != null) instance = null; }
​
    public static T CreateInstance()
    {
        if (Instance != null) Instance.OnCreate();
        return Instance;
    }
​
    protected virtual void OnCreate()
    {
​
    }
​
}

0×02 相关资源

- Eof -