游戏设计模式与实现之:单例模式 与 单例模版

15 篇文章 0 订阅
13 篇文章 5 订阅

GoF解释:

确保类只有一个实例对象,并提供一个全局方法去调用这个对象。

模式说明:

单例模式通常被使用于一些全局一定唯一的,只关心调用功能,而不关心这个从哪里生成的类,并且这个类通常不应该参与到实际游戏交互子系统的协同工作,负责的功能大量单一且需要统一调度。在项目中,符合这个需求的一般是工具类,如音效管理,UI管理,本地表数据读取等等。

案例说明:音效管理,现有MusicManager类统一管理音效的播放

1.不使用单例:每个对象都需要持有一个MusicManager对象,这个对象可以是自己New出来,也可以是初始化时使用依赖注入的方法传入。这样我们每个需要使用音效播放的类都需要维护一个MusicManager对象。会让代码变得繁琐,而且稍有不慎就会多创建MusicManager对象,这样唯一性被破坏。有些需要全局统一调度的流程就不在起效。比如为了优化,同一时间播放的同种音效个数有上限,一旦多加入一个MusicManager对象,那么这个上限就会被破坏。代码所需的严谨程度增加,但是维护成本也增加了。

假设使用依赖注入得到音效管理类

class Hero{

	private MusicManager mMusicManager ;
	
	public Hero(MusicManager musicManager){
		mMusicManager = musicManager;
	}
	void Scream(){
		mMusicManager.playSound('Scream');
	}	
}

这样的代码阅读和维护都有一点难度

2.使用单例模式:首先创建MusicManager单例

class MusicManager{
	
	private static MusicManager instance = null;
	
	public static MusicManager Instance{
		get{
		 	if(instance==null){ 
 				instace = new MusicManager();
 			}
 			return instace;
		}
	}
	
	//为了保证全局唯一,私有化构造函数
	private MusicManager(){ }
	
	public void playSound(string soundName ){ 
		//TODO 
	}
}

Hero调用实现

class Hero{
	void Scream(){
		MusicManager.Instance.playSound('Scream');
	}	
}

代码一下精简了很多,也不需要多维护一个变量。

提到了单例一般还会提到单例模版,但是由于并不建议大量的使用单例,所以单例模版的意义也就很小了。这里也介绍一下,并且会看一下上面的音效单例,其实还有一个问题,线程安全,当单例没有生成的时候,两个线程同时去调用MusicManager单例会出现什么情况?会同时生成两个单例对象。所以下面基于线程安全的情况下介绍单例模版。

public class Singleton<T> where T:class ,new(){
	
	private static readonly object syslock = new object();
	
	private static T instance = null;
	
	public static T Instance{
		get{
			if(instance == null){//两层空判断,保证在安全模式下生成单例对象之后,没有额外消耗
				lock (syslock){
					//先获得锁,在判断是否需要new对象,
					//但是每次都锁再去判断,是会增加消耗的,所以在外面再加一层空判断,
					if(instance == null){ 
						instance = new T();
					}
				}
			} 
			return instance;
		}
	}
}

此时音乐单例的实现:

public class MusicManager:Singleton<MusicManager>{
	public void playSound(string soundName){ 
		//TODO
	}
}

这样代码又精简了不少,但是使用单例模版又会产生一个很严重的问题:使用泛型T制作单例模版,意味着类需要有公共的无参构造函数。无法私有化构造函数,也就无法从代码层面强制规范全局只有一个,协同开发中需要额外的协调说明。这个如果有解决方法,也可以在评论中告诉博主。

关于单例模式是否应该应用于项目,不同的开发者有不同的结论,因为滥用单例会造成项目设计思考不周,破坏项目结构合理性问题。但是在某些模块适当的使用单例,同样也能精简代码,降低耦合。我的结论是结合项目整体情况使用、慎用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值