人生第一个博客,从设计模式开始 ------------------ 单例模式(基于Unity3d)

第一次写博客,有点紧张,莫介意。

下面谈一下单例模式:简单地说就是一个static类,一个只能实例化一次并提供唯一接口的静态类。

最简单的单例模式,当然这是在没有继承自MonoBehaviour的C#类:

public class Instance
{
    private static Instance _instance;
    public static Instance GetInstance
    {
        get{
               if(_instance == null)
                    _instance = new Instance();
               return _instance;     
           }
    }
}

继承自MonoBehavioru的C#类大概是这么写的(ps:我刚入Unity3d的时候的写法,不知道别人怎么写的,反正很蠢)

public class Instance:MonoBehaviour
{
    public static Instance _instance;
    void Awake()
    {
        _instance = this;
    }
}

我的天,这种写法不仅仅需要每个单例都需要重复这样子的代码,很累的有木有!

所以大戏就来了,我们可以写一个继承于MonoBehaviour的单例泛型类不就行了,下面上代码!

public class Sinleton<T> :MonoBehaviour where T :Sinleton<T>
{
    private static T instance;
    public static T Instance
    {
        get{
                if(instance == null)
                {
                    GameObject singleton = new GameObject();
                    instance = singleton.AddComponent<T>();
                    singleton.name = singleton.AddComponent<T>().GetType().ToString();
                }
                return instance;
           }
    }

    void Awake()
    {
        instance = this.GetComponent<T>();
    }
    
    public void OnDestroy()
    {
        instance =null;
    }
}

enmmmmm.....

可能很不完善,不过Unity3D毕竟很少用到多线程的,如果有多线程的情况下,可能还需要更改一下,需要锁一下(PS:单层锁)。

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

    private static readonly object locker = new object();

    public static T Instance
    {
        get{
                lock(locker)
                {
                    if(instance == null)
                    {
                        GameObject singleton = new GameObject();
                        instance = singleton.AddComponent<T>();
                        singleton.name = singleton.AddComponent<T>                        
                                          ().GetType().ToString();
                    }
                    return instance;
                }
           }
    }

    void Awake()
    {
        instance = this.GetComponent<T>();
    }
    
    public void OnDestroy()
    {
        instance =null;
    }
}

给程序加一个锁,然后当另一个线程想调用的时候,会锁上,不会让它去调用这个单例了。这个时候会出现一个问题就是当每次另一个线程调用这个单例的时候就会出现一个问题就是:每次都会去锁一下,很浪费性能啊,所以这个时候我们需要在锁上之前需要判定一下是否存在该单例实例,然后再加锁处理(PS:双层锁)(PS:网上的说法,照搬下来的,莫怪!)。

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

    private static readonly object locker = new object();

    public static T Instance
    {
        get{
                if(instance == null)
                {
                    lock(locker)
                    {
                        if(instance == null)
                        {
                            GameObject singleton = new GameObject();
                            instance = singleton.AddComponent<T>();
                            singleton.name = singleton.GddComponent<T>                        
                                          ().GetType().ToString();
                        }
                    }    
                }
                return instance;
           }
    }

    void Awake()
    {
        instance = this.GetComponent<T>();
    }
    
    public void OnDestroy()
    {
        instance =null;
    }
}

这个时候差不多解决了多线程问题了,不过因为很少用到多线程,所以我基本没用过,enmmmmm....,谁去试试水的?

(ps:不过很多前辈都这么说的,我想应该都试过水了。)

好了基本就这样子。下面上使用的代码:

public class Test:Singleton<Test>
{
    public void Test()
    {
        Debug.Log("isRunning");
    }
}    

public class TestMonoBehaviour :MonoBehaviour
{
    void Start()
    {
        Test.Instance.Test();//测试用的,如果有问题,自行解决哦,下面评价也行,我会随时查看的。
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值