Jenner's Blog

不变秃,也要变强!

0%

单例模式

几种单例模式

懒汉

  • 非线程安全,多线程可以同时生成新的实例。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Singleton {
    // 静态,实例化只有一次
    private static Singleton singleton;
    // 构造函数私有化
    private Singleton() { }
    //通过getInstance()的方法来获取实例
    public static Singleton getInstance() {
    if (singleton == null) {
    singleton = new Singleton();
    }
    return singleton;
    }
    }

    饿汉

  • 类初始化就创建单例对象,消耗资源,而又不是马上使用。
  • 线程安全
    1
    2
    3
    4
    5
    6
    7
    public class Singleton {
    private static readonly Singleton instance = new Singleton();
    private Singleton (){}
    public static Singleton getInstance() {
    return instance;
    }
    }

    双重校验锁

  • 线程安全
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public static class Singleton<T> where T : class,new() 
    {
    private static T _Instance;
    private static object _lockObj = new object();
    /// <summary>
    /// 获取单例对象的实例
    /// </summary>
    public static T GetInstance()
    {
    // 检查1
    if (_Instance != null) return _Instance;
    // 锁
    lock (_lockObj)
    {
    // 检查2
    if (_Instance == null)
    {
    // 创建实例
    var temp = Activator.CreateInstance<T>();
    // 原子操作:互换
    System.Threading.Interlocked.Exchange(ref _Instance, temp);
    }
    }
    return _Instance;
    }
    }

Unity中的使用

简单懒汉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton<T> where T : new()
{
    static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new T();
            }
            return instance;
        }
    }
}

全局单例,不销毁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public bool global = true;
    static T instance;
    // 普通单例的写法
    // MonoSingleton的写法一般是在Awake()中instance=this
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = (T)FindObjectOfType<T>();
            }
            return instance;
        }
    }

    void Start()
    {
        if (global)
        {
            // 清除新生成的实例,防止堆积
            if (instance != null && instance != this.gameObject.GetComponent<T>())
            {
                Destroy(this.gameObject);
                return;
            }
            DontDestroyOnLoad(this.gameObject);
            instance = this.gameObject.GetComponent<T>();
        }
        this.OnStart();
    }
// 子类Start替换为OnStart
    protected virtual void OnStart() { }
}

即使解决了实例堆积的问题,但多个子类重复生成实例再销毁也太冗余操作了,可以挂一个全局的单例管理器,记录哪些MonoSingleton已经被生成了。

点击下方打赏按钮,获得支付宝二维码