在最简单的单例模式上遇到了坑。。。这里记录一下,以防以后又忘记了
一般的单线程单例模式,可以用共有方法或者属性去实现全局访问点,这边的话我用的是公有方法
/// <summary>
/// 单线程单例模式的实现
/// </summary>
public class Singleton
{
// 定义一个静态变量保存类的实例
private static Singleton uniqueInstance;
// 构造函数私有,防止外界创建该类实例
private Singleton()
{
}
/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 判断类实例是否存在,不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
如果是要支持多线程访问,那么就在获取实例的方法内增加线程锁(lock),具体代码就不写了
然后说一下,我遇到的问题
/// <summary>
/// 单线程单例模式的实现
/// </summary>
public class Singleton :MonoBehaviour
{
// 定义一个静态变量保存类的实例
private static Singleton uniqueInstance;
// 构造函数私有,防止外界创建该类实例
private Singleton()
{
}
/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 判断类实例是否存在,不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
我写了一个单例,然后继承自MonoBehaviour,然后里面还有一些数据和代码,这边没有具体写进去,然后遇到的问题是:每次存入数据到这个类里的字典或者字段里的数据,在下次调用的时候都会变成空。
经过代码的断点和debug的调试,发现存入数据后,数据能看到保存进去了,但是再调用GetInstance()方法获取实例时,数据会被清空,uniqueInstance会变为null,就算是你在申明uniqueInstance字段的时候,将它实例化了,也会变为null
具体什么原因,我没有很确定的答案,只能通过调试回避这个问题,看到的大佬知道是啥原因的,也可以给本菜鸡解答一下。
我这边用了两种方法,在继承MonoBehaviour的情况下实现单例
第一种,直接在Awake()方法中赋值,然后公有方法直接返回这个类,为什么不在公有方法中赋值,因为静态方法不能使用this关键字
/// <summary>
/// 单线程单例模式的实现
/// </summary>
public class Singleton :MonoBehaviour
{
// 定义一个静态变量保存类的实例
private static Singleton uniqueInstance;
// 构造函数私有,防止外界创建该类实例
private Singleton()
{
}
private void Awake()
{
uniqueInstance = this;
}
/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
return uniqueInstance;
}
}
第二种是修改实例为空时的处理,不再是新new一个,而是去场景中查找,如果没有就添加,然后返回查找到的结果或者添加的脚本
/// <summary>
/// 单线程单例模式的实现
/// </summary>
public class Singleton :MonoBehaviour
{
// 定义一个静态变量保存类的实例
private static Singleton uniqueInstance;
// 构造函数私有,防止外界创建该类实例
private Singleton()
{
}
/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
if (uniqueInstance== null)
{
//如果uniqueInstance为空,就在场景中查找是否存在此类的实例
uniqueInstance= FindObjectOfType(typeof(Singleton)) as Singleton;
//如果uniqueInstance还是为空,就创建一个空物体并添加此类
if (uniqueInstance== null)
{
GameObject obj = new GameObject();
uniqueInstance= obj.AddComponent<Singleton>();
}
}
return uniqueInstance;
}
}
由两个上面连个解决方法猜想,unity的挂在脚本实例化出来的类,和直接new出来的类是有区别的,不能相互之间识别