Unity---游戏设计模式(3)之单例模式




1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

方法1

不推荐的方式1:只能用于单线程。
因为有可能会出现两个线程同时判断 _instance==null 然后都创建一个实例。这就不满足单例模式了。

	//sealed修饰符,不可被继承或重写
    public sealed class Singleton1
    {
        private static Singleton1 _instance = null;
        public static Singleton1 Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Singleton1();
                return _instance;
            }
        }
    }

方法2

不推荐的方式2:虽然能多线程但效率不高。
这样当一个线程加锁时,另一个线程只能等待。但是加锁比较耗时,所以效率比较低。

    public sealed class Singleton2
    {
		//readonly动态变量修饰符
        private static readonly object locked = new object();

        private static Singleton2 _instance = null;
        public static Singleton2 Instance
        {
            get
            {
                lock (locked)
                {
                    if (_instance == null)
                        _instance = new Singleton2();
                }
                return _instance;
            }
        }
    }

方法3

还可以的方式3:前后两次if语句判断。
在加锁前再判断一次是否为空,这样就只会在第一次创建的时候加锁了。但是此方法比较麻烦,还有更好的方法。

    public sealed class Singleton3
    {
        private static readonly object locked = new object();

        private static Singleton3 _instance = null;
        public static Singleton3 Instance
        {
            get
            {
                //这样不为空时,就不会再加锁
                if (_instance == null)
                {
                    lock (locked)
                    {
                        if (_instance == null)
                            _instance = new Singleton3();
                    }
                }
                
                return _instance;
            }
        }
    }

方法4

推荐的方式4:静态构造函数。
静态构造函数的调用并不是由程序员决定的,而是在第一次用到Singleton4时就会被调用。所以有可能我们还没有调用 Singleton4.Instance 的时候就已经被创建了,可能会降低内存使用效率。

    public sealed class Singleton4
    {
        //静态变量在静态构造函数被调用时初始化,所以只会初始化一次
        private static Singleton4 _instance = new Singleton4();
        public static Singleton4 Instance
        {
            get
            {
                return _instance;
            }
        }
    }

方法5

推荐的方式5:按需创建实例。
由Nested的静态成员完成,实现按需初始化。

    public sealed class Singleton5
    {
        public static Singleton5 Instance
        {
            get
            {
                return Nested._instance;
            }
        }
            
        class Nested
        {
            static Nested()
            {

            }
			//internal修饰符。只有同一个程序集可访问,可以跨类。
            internal static readonly Singleton5 _instance = new Singleton5();
        }
    }

2、单例模式优缺点

优点

  1. 只有一个实例,减少了内存消耗和系统性能开销。

缺点

  1. 单例类的职责过重,在一定程度上违背了“单一职责原则”。
  2. 单例如果滥用会导致特殊一些问题。
  3. 单例类想扩展,只能修改源代码。有点违反开闭原则。
原文地址:https://www.cnblogs.com/Fflyqaq/p/11576524.html