您当前的位置: 首页 >  unity

野奔在山外的猫

暂无认证

  • 6浏览

    0关注

    85博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Unity】单例 Singleton

野奔在山外的猫 发布时间:2021-03-31 10:20:54 ,浏览量:6

游戏引擎:Unity 版本:2019.4.6f1 【2017版本以上均可】 编译平台:Visual Studio 2019  

一、了解单例

  单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。

二、思路

  单例Singleton遵从以下顺序(由1至4):

1234构造函数私有化提供静态类自身的只读属性创建对象实例方法

  注:以下脚本按照有缺点进行优化,具体见每类型最后一项。

2.1 饿汉写法 2.1.0 什么是饿汉写法?

  答:创建对象的时机最早。

2.1.1 代码块
class Singleton
	{
		//1.构造函数私有化
		private Singleton() { }

		//2.提供静态自身类型的只读属性
		public static Singleton Instance { get; private set; }
		
		//3.创建对象
		static Singleton()
		{		    
		    Instance = new Singleton();
		}
		
		//4.实例方法
		public void Test() { }
	}
2.1.2 缺点

  在【流程3】过程中,由于在静态构造函数中创建对象(属性赋值),可能时机过早。这里的时机过早——例如我只想访问静态类成员变量,造成在单例Singleton中必须过早的创建实例对象。最终造成的不必要的性能开支。

2.2 饿汉写法(改进)

  按需加载思想:需要时加载,不需要不加载。改进后的代码按照你需要访问属性,我创建对象;不需要则不用创建。如果我没有实例,则创建;有之则返回属性,不需反复创建。

2.2.1 代码块
class Singleton
{
	//1.构造函数私有化
	private Singleton() { }
		
	#region 2.创建对象-按需加载
	//2.静态类自身字段
	private static Singleton instance;
	//2.静态类自身属性
    public static Singleton Instance
	{
		get
		{
			if (instance == null) { instance = new Singleton(); }				
			return instance;
		}
	}
	#endregion

	//3.实例方法
	public void Test() { }		
}
2.2.2 缺点
            if (instance == null) { instance = new Singleton(); }	

  因为是按需加载,在多线程中,可能多个线程同时访问Instance属性,造成同时满足条件并创建对象。

2.3 饱汉写法 2.3.0 什么是饱汉写法?

  答:创建对象的时机最晚。

2.3.1 代码块

  多线程遇到lock会自动停止,等待前一个线程结束后执行。避免多个线程的同时执行。

class Singleton02
    {
        private static object locker = new object();  
        
        //1.构造函数私有化
        private Singleton02() { }
		
		//2.静态自身类型字段
        private static Singleton02 instance;  
       	//2.静态自身类型属性
        public static Singleton02 Instance  
        {
            get
            {
            	//加锁
                lock (locker)
                {
                    //缺点:每次访问Instance属性,都会判断线程锁,造成读取缓慢
                    if (instance == null) { instance = new Singleton02(); }
                    return instance;
                }
            }
        }
       
       	//3.实例方法
	    public void Test() { }	
    }
2.3.2 缺点

  每次访问需要进行一次 lock(locker) 的判断,存在不必要的性能消耗。

2.4 饱汉写法(改进) 2.4.1 代码块

  双重检测机制:第一次判断为null,去new一个对象后,第二次判断就不会null。

class Singleton02
{
    private static object locker = new object();
	
	//1.构造函数私有化
    private Singleton02() { }
    //2.静态自身类型字段
    private static Singleton02 instance;
    //2.静态自身类型属性
    public static Singleton02 Instance
    {
        get
        {
            //双重检测
            //第一层:避免每次访问属性都判断线程锁
            if (instance == null)
            {
                lock (locker)
                {
                    //第二层:避免重复创建对象
                    if (instance == null) { instance = new Singleton02(); }
                }
            }
            return instance;             
        }
    } 

	//3.实例方法
	public void Test() { }	
}
三、为什么要选择单例类?而不是静态类 单例类静态类游戏对象可创建(附加于)实例成员可定义不可定义接口可实现不可实现 四、更多说明

  文章如有错误,请联系笔者修正。

关注
打赏
1659777066
查看更多评论
立即登录/注册

微信扫码登录

0.0366s