举例讲解C#编程中对设计模式中的单例模式的运用

2019-12-26 18:03:32丽君

代码大部分都比较容易看懂,下面介绍几点注意的地方:
当我们在其他代码里需要访问某个单例时,只需调用getInstance函数即可,参数是需要访问的脚本的名字。我们来看一下这个函数。它首先判断所有单例所在的容器m_Container是否为空(实际上就是场景中是否存在一个Gameobject,上面捆绑了一个Singleton脚本),如果为空,它将自动创建一个对象,然后以“Singleton”命名,再捆绑Singleton脚本。m_SingletonMap是负责维护所有单例的映射。当第一次访问某个单例时,它会自动向m_Container上添加一个该单例类型的Component,并保存在单例映射中,再返回这个单例。因此,我们可以看出,单例的创建完全都是自动的,你完全不需要考虑在哪里、在什么时候捆绑脚本,这是多么令人高兴得事情!
在Awake函数中,有一句代码DontDestroyOnLoad (gameObject);,这是非常重要的,这句话意味着,当我们的场景发生变化时,单例模式将不受任何影响。除此之外,我们还要注意到,这句话也必须放到Awake函数,而不能放到Start函数中,这是由两个函数的执行顺序决定的,如果反过来,便可能会造成访问单例不成功,下面的例子里会更详细的介绍;
在OnApplicationQuit函数中,我们将销毁单例模式。
最后一点很重要:一定不要在OnDestroy函数中直接访问单例模式!这样很有可能会造成单例无法销毁。这是因为,当程序退出准备销毁单例模式时,我们在其他脚本的OnDestroy函数中再次请求访问它,这样将重新构造一个新的单例而不会被销毁(因为之前已经销毁过一次了)。如果一定要访问的话,一定要先调用IsCreatedInstance,判断该单例是否存在。

.NET实现单例模式的类
理解完了单例模式之后,菜鸟又接着问了:.NET FrameWork类库中有没有单例模式的实现呢?

经过查看,.NET类库中确实存在单例模式的实现类,不过该类不是公开的,下面就具体看看该类的一个实现的(该类具体存在于System.dll程序集,命名空间为System,大家可以用反射工具Reflector去查看源码的):


// 该类不是一个公开类
  // 但是该类的实现应用了单例模式
  internal sealed class SR
  {
    private static SR loader;
    internal SR()
    {
    }
    // 主要是因为该类不是公有,所以这个全部访问点也定义为私有的了
    // 但是思想还是用到了单例模式的思想的
    private static SR GetLoader()
    {
      if (loader == null)
      {
        SR sr = new SR();
        Interlocked.CompareExchange<SR>(ref loader, sr, null);
      }
      return loader;
    }
    // 这个公有方法中调用了GetLoader方法的
    public static object GetObject(string name)
    {
      SR loader = GetLoader();
      if (loader == null)
      {
        return null;
      }
      return loader.resources.GetObject(name, Culture);
    }
  }