程序篇04:C#设计模式——单例模式 - kudan-game/ArtArtist-Repo GitHub Wiki

本篇介绍如何定义和使用C#中的单例模式

学习更多设计模式请直接访问 https://www.cnblogs.com/zhili/p/DesignPatternSummery.html

单例模式(SingleTon)是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

在Unity中,一些公共组件的设计和开发,例如应用程序、运行设备和环境(一个Unity不可能对应两个应用程序),经常会用到单例模式。

特点

  1. 某个类只能有一个实例
  2. 它必须自行创建这个实例
  3. 它必须自行向整个系统提供这个实例。

先来看一个简单的实现:

public class SingleTonTest
{
    //由于没有构造函数,无法使用 new SingleTonTest() 创建出类的实例
    //instance是静态类型唯一实例化对象,用Instance封装属性
    private static SingleTonTest instance = null;

    //类的静态私有属性,无法被实例引用,可以被SingleTonTest.Instance.GetAmount()调用。
    private static readonly int amount = 9889; 

    //此处使用属性的封装来创建单例实例  
    public static SingleTonTest Instance         
    {
        get
        {
            if (instance == null)
                instance = new SingleTonTest();
            return instance;
        }
    }
    //测试方法
    public void TestInstance()
    {
        Debug.Log("Method SingleTonTest.TestInstance used amount: " + instance.GetAmount());

    }
    public int GetAmount()
    {
        return amount;
    }
}

加入锁机制,防止多线程创建对象实例的时候,创建出多个实例,改进一下代码(双重锁):

public class SingleTonTest
{
    //由于没有构造函数,无法使用 new SingleTonTest() 创建出类的实例
    //instance是静态类型唯一实例化对象,用Instance封装属性
    private static SingleTonTest instance = null;

    //类的静态私有属性,无法被实例引用,可以被SingleTonTest.Instance.GetAmount()调用。
    private static readonly int amount = 9889; 

    // 定义一个标识确保线程同步
    private static readonly object locker = new object();

    //此处使用属性的封装来创建单例实例
    public static SingleTonTest Instance         //此处使用属性的封装来创建单例实例
    {
        get
        {
            // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
            // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
            // 双重锁定只需要一句判断就可以了

            if (instance == null)
            {
                lock (locker)
                {
                    if (instance == null)
                        instance = new SingleTonTest();
                    return instance;
                }
            }
        }
    }
    public void TestInstance()
    {
        Debug.Log("Method SingleTonTest.TestInstance used amount: " + instance.GetAmount());

    }
    public int GetAmount()
    {
        return amount;
    }
}

简单的静态类调用示例:

SingleTonTest.Instance.TestInstance();
int amount = SingleTonTest.Instance.GetAmount()