1.6.1 模式意图:
对于游戏中的某些类来说,只有一个实例很重要,例如各种Manager管理类,在系统中多处可调用,且始终保持独一无二的特性,可以使用设计模式中的单例模式来完成这类任务。
1.6.2 模式概念:
属于创建型模式,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
1.6.3 模式元素:
- 单例(Singleton、Singleton
)
1.6.4 代码示例:
using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
B.泛型版本
public sealed class Singleton<T> where T : class, new()
{
public const string Name = "Singleton";
static Singleton() { }
private Singleton() { }
private static volatile T instance = null;
private static readonly object syncLock = new object();
public static T Instance
{
get
{
if (instance == null)
{
lock (syncLock)
{
if (instance == null)
{
instance = new T();
}
}
}
return instance;
}
}
}
C.Lazy类版本
如果使用的是.NET 4(或更高版本),可以使用Lazy类型使延迟变得非常简单。
using System;
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
D.Unity版本
using UnityEngine;
public class SingletonMonoBehaviour<T> : MonoBehaviour where T : SingletonMonoBehaviour<T>
{
static SingletonMonoBehaviour() { }
protected SingletonMonoBehaviour() { }
private static volatile T instance = null;
public static T Instance
{
get
{
return instance;
}
}
protected virtual void Awake()
{
instance = this as T;
}
}
1.6.5 写法对比:
略
1.6.6 模式分析:
- 只有一个实例,最大限度减少了内存的开销,避免频繁的创建和销毁实例。
- 始终保持唯一实例,易于控制对该实例的访问途径。
- 可全局共享访问
不足之处:
- 不方便扩展
- 如果大量使用单例,并更改单例类中某处,可能会造成牵一发而动全身的情况。
1.6.7 应用场景:
要求全局保持唯一的实例且可共享访问。
1.6.8 小结:
最好使用延迟加载的模式进行单例,避免在同一时间单例初始化过多造成性能瓶颈。在享受单例优点的同时,要减少系统多处使用单例的情况,降低因过多使用单例而导致后期维护成本过高。