单例模式(Singleton Pattern)的使用

单例模式是最简单的设计模式之一

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

一、单例模式优点

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例

保证类在内存中只有一个对象,减少了内存开销;

注意!!:

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

二、单例模式应用场景

  1. 资源管理器,资源对象数据的加载和卸载(无状态不需要实例化的对象);
  2. 生命周期在游戏中永不消毁的对象
  3. 单一客户端连接服务器等;

三,单例模式的设计思想(复习时选看)

(1)不允许其他程序用new对象。

因为new就是开辟新的空间,在这里更改数据只是更改的所创建的对象的数据,如果可以new的话,每一次new都产生一个对象,这样肯定保证不了对象的唯一性。

(2)在该类中创建对象
因为不允许其他程序new对象,所以这里的对象需要在本类中new出来

(3)对外提供一个可以让其他程序获取该对象的方法

因为对象是在本类中创建的,所以需要提供一个方法让其它的类获取这个对象。

四,单例模式的使用

unity继承monobehavior的单例

只需要在Awake()里面,添加一句instance = this;

注意在Unity中不要使用new来创建MonoBehaviour实例

public class  test : MonoBehaviour 
{
  private static test instance;//1. static!!
  void Awake () 
  {	
           instance = this;
  }
    public static test GetInstance() 
    {
        
            return instance;
        
    }
}

使用方式

test2.GetInstance().方法/属性/等  ;

unity中范型写法(可不用双重锁)

public class A<T> where T : new()//确保无参
{
	private static T instance;
	
	public static T GetInstance()
	{

		if (instance == null)
		{
			instance = new T();
		}
		return instance;
	}
}

public class B : A<B>
{
}

C#版本的 普通类单例。

饿汉模式(常用)

public class Singleton
    {
        // 自行预先实例化,内部定义自己唯一实例,只供内部使用 //
        private readonly static  Singleton Instance = new Singleton();

        private Singleton() 
        {
            // Do Something
        }

        // 提供外部访问的静态方法,来对内部唯一实例进行访问 //
        public static Singleton GetInstance()
        {
            return Instance;
        }
    }

二 懒汉模式[线程不安全,不可用]

public class Singleton {

   //1  private satic
   private static Singleton instance  = null;
    //2 提供私有构造函数;这样该类就不会被其他类实例化
   private Singleton(){}

   //3 获取唯一可用的对象
   public static Singleton GetInstance()
   {
     
          if (instance == null )
                instance = new Singleton();
          return instance;//返回唯一实例,以便外部调用
      
   }

   
   
}

使用方式

Singleton.GetInstance().方法/属性/等    ;
  • 两者比较:
  1. 所谓饿汉式,就是直接创建出类的实例化;

而对于懒汉式,就是在需要的时候再创建类的实例化

  1. 饿汉式:简单来说就是空间换时间,因为上来就实例化一个对象,占用了内存,(也不管你用还是不用)(但是这个浪费可以忽略,所以这种方式也是推荐使用的)。
    懒汉式:简单的来说就是时间换空间,与饿汉式正好相反
  • 饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变

以下解释引用

public static Singleton GetInstance()
{
		//判断singleton是否为null,如果为null,即判定需要实例化
		if (singleton == null)
        {   //
				
            singleton = new Singleton();
		}
		return singleton;
}

比如,现在有A线程和B线程,A线程刚好在这个GetInstance()方法中,刚刚判断完非空(此时为null),即需要创建实例,然而,就是这么巧,B线程抢到了CPU的执行权,A线程sleep了,这时,B线程也进行了这个判断,和A一样,都需要创建实例,而这时,A也抢到了CPU,这时,B就sleep了,然后A执行了实例化后,B又抢到CPU执行权,然后B也实例化,这时,出现问题了,A和B都实例化了一个对象,这就是赤果果的两个对象呀,单例呢,唯一呢,全都没了(这将导致第一个实例化的数据丢失)。

三 双重校验锁模式的懒汉式【线程安全的】

using System.Threading;//留意

public class Singleton {
	/**
	 * 懒汉式变种,属于懒汉式中最好的写法,保证了:延迟加载和线程安全
	 */
	private static Singleton instance=null;
	private Singleton() {};

	public static Singleton GetInstance()
    {
	 	if (instance == null) //进行了两次null检查
        {  
          synchronized (Singleton.class)
          { //synchronized之一,在方法定义时使用,多线程状态下,这个方法只能同时被同一个线程执行;
              //可换用lock
              if (instance == null)
              {  
            	  instance = new Singleton();  
              }  
          }  
      }  
      return instance;  
}

访问方式

Singleton instance = Singleton.GetInstance();//获得引用

四枚举[推荐使用,但无法继承]

public enum SingletonEnum
 {
 	 instance; 
 
	 private SingletonEnum() {}
 
 	public void method(){
 }

}
访问方式

SingletonEnum.instance.method();

五 泛型(结合双重锁)

在一个案例中,我们可能需要使用到不止一个单例模式类,甚至更多。那么此时,使用泛型单例模式模板来实现单例模式,我们可以有两种不同的方法来实现它:

4.3.1 首先我们来看下泛型模板,我们对泛型类进行约束,T只能是一个Class,并且有一个公共无参构造函数,代码如下:

class Singleton<T> where T: class,new()  
{  
    private static T instance;  
    private static readonly object syslock=new object();  
  
    public static T GetInstance()   
    {  
        if (instance == null)  
        {  
            lock (syslock) {  
                if (instance == null)  
                {  
                    instance = new T();  
                }  
            }  
        }  
       return instance;  
    }  
} 

class B : Singleton<B> {  
    public void ss() {  
        Console.WriteLine("111");  
    }  
}

萌新一枚,咳咳,不是食物链顶端的那种萌新,若有误,望指正