c#设计模式-1.单例模式

如果出现单例空指针异常,我猜你会这样写(因为我第一次这样写):

public class Test : MonoBehaviour
{
	private static AStarManager instance = null;
    public static AStarManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new AStarManager();

            }
            return instance;
        }
    }
}

在你第二次使用单例时就会出现空指针异常,什么原因呢?

是因为继承MonoBehaviour和不继承MonoBehaviour的单例是不一样的,且大多数用的是不继承MonoBehaviour的单例

不继承的单例模式:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class baseManager<T> where T:new()
{
    private static T instance;

    public static T GetInstance()
    {
        //泛型类创建实例要写泛型约束new()
        if (instance == null)
            instance = new T();
        return instance;
    }
}

然后继承baseManager就可以使用了

public class AStarManager : baseManager<AStarManager>
{
	//防止外部创建该实例
	private AStarManager()
	{
	}
}

2.然后就是继承MonoBehaviour的情况:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//继承MonoBehaviour的单例模式对象,需要自己保证它的唯一性
public class SingleMono<T> : MonoBehaviour where T:MonoBehaviour
{
    private static T instance;

    public static T GetInstance()
    {
        //继承MonoBehaviour,不能new
        //只能通过拖动脚本或者addcomponent,如果拖动多个脚本,就不是单例模式了
        //所以自己实现
        return instance;
    }
    protected virtual void Awake()
    {
        instance = this as T;
    }
}

test.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test : SingleMono<test>
{
    protected override void Awake()
    {
        base.Awake();
    }
    // Start is called before the first frame update
    void Start()
    {
        print(test.GetInstance().name);
    }
    
}

第二种写法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SingleAutoMono<T> : MonoBehaviour where T : MonoBehaviour 
{
    private static T instance;

    public static T GetInstance()
    {
        if (instance == null)
        {
            GameObject obj = new GameObject();
            obj.name = typeof(T).ToString();
            DontDestroyOnLoad(obj);
            instance = obj.AddComponent<T>();
        }
        return instance;
    }
}

继承MonoBehaviour的单例,继承SingleMono的脚本只能挂载到一个物体身上,否则就不是单例了,这样就不是很好,而不继承MonoBehaviour的单例,不需要挂载,直接继承即可使用

对于多线程的情况:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class baseManager<T> where T:new()
{
    private static T instance;
    //定义标识让线程同步
    private static readonly object locker = new object();

    public static T GetInstance()
    {
        /*当第一个线程运行到这里,会对Locker对象加锁
         当第二个运行到这里,检测到locker对象为加锁状态,该线程就会挂起等待第一个线程解锁
         双重否定
         */
        if(instance==null)
        {
            lock(locker)
            {
                //泛型类创建实例要写泛型约束new()
                if (instance == null)
                    instance = new T();               
            }
        }
        return instance;      
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值