算法、数据结构、与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design)
算法、数据结构、与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design)
作者: Compasslg 李涵威
1. 什么是单例设计(Singleton Design)
在学校学习面向对象编程中的一些常用的设计模式时,我第一次系统的接触到了单例设计(Singleton Design),或者说单例设计模式。所谓设计模式(Design Pattern),指的是在软件开发中针对一些常见问题提出的可复用的解决方式;而单例设计便是针对在面向对象编程中一些只会被实例化一次、或只允许一个实例(instance)存在的类(class)而出现的设计模式。这种对象/实例通常是作为工程中一个全局管理的存在,因此他们会在整个工程的各个角落被调用。由于在面向对象编程的设计中你往往需要通过储存一个对象的地址来随时调用其中的方法和数据,这便可能会造成同一个对象的地址被储存很多次的情况。
在单例设计模式中,你可以通过将单例目标类的构造器(Constructor)设置为private类型使该类无法在外部被实例化,然后在这个类的内部实例一个自己的对象并将其储存在一个静态变量中。同时,你也可以写一个公开的静态getter方法来作为获取和调用这个单例的方式。如此这般,通过使用单例设计模式,你便可以实现一个全局有且只有一个实例的类。具体实现方式我会在下一个部分举例说明。
2. 如何使用单例设计 (Java 范例)
Java是单例设计最常被应用的语言。一个最典型的例子便是java.lang.Runtime中的Runtime class. 该类无法被实例,你可以通过其中的静态方法Runtime.getRuntime()来调用他的单例 object。
除此之外,在软件和游戏开发中还有很多的功能可以利用单例设计实现,以下便是一个用Java通过单例设计实现的可能被应用在游戏和软件中的音频管理器(AudioManager)的简单模型:
/**===========================================
这是一个在游戏中管理音频文件的类,有且只有存在一个。
因此使用单例设计模式。
*===========================================*/
class AudioManager {
// 设置为private,外部便不能再修改这个单例。
private static instance;
// 单例中实际储存的内容。这里使用的数据类型只是作为该单例的应用背景(context),仅供参考,在AudioManager中具体要用什么数据类型来储存音频资料应视情况而定
private HashMap<String, AudioClip> clips;
// ... 此处略过其他AudioManager可能需要的变量 ...
// private 构造器,无法被外部调用
private AudioManager(){
clips = new HashMap<String, AudioClip>();
// ... 此处略过其他可能需要初始化的东西
}
// 单例的 Getter。会且只会实例一个该类的实例。
// 如果担心第一次调用时的速度影响,可以在loading的时候统一将单例设计的类的getInstance方法调用一次
public static AudioManager getInstance(){
// 实例化如果此前没有实例
if (instance == null){
instance = new AudioManager();
}
return instance;
}
// 播放一段音频的方法
public void playAudioClip(String clipName){
clips.get(clipName).play();
}
}
以下是调用方法:
public static void main(String[] args){
AudioManager.getInstance().playAudioClip("BGM");
}
3. 游戏开发中的运用 (Unity)
在游戏开发过程中,我们常常会需要应用到一些负责全局管理的并且只会同时存在一个实例的类,例如上面提到的AudioManager,还有负责管理游戏状态或界面的StateManager和SceneManager,我自己写游戏也经常会写一个负责数据管理的类DataManager。这些类都是有且只有一个实例存在,都可以通过 Part 2 中的方法依样画葫芦实现和调用,这里就不复述了。
在使用Unity开发游戏时,我们往往会要用到一个GameController。在我接触单例设计之前,我都会选择在要用到他的地方存一个变量,然后通过在编辑器中把它拖到inspector,或者使用
gameController = GameObject.FindWithTag("GameController");
来找到它。久而久之,这样不但使代码变得混乱且重复,在速度上和内存空间上也给我一种很浪费的感觉。这个时候,我们可以利用Singleton Design思想,在GameController中加一个静态变量
public class GameController : MonoBehaviour {
private static GameController instance;
void Awake(){
// ... 省略其他初始化相关代码 ...
instance = this;
}
public static GameController GetInstance(){
return instance;
}
}
这样,虽然这个类是绑定Unity中的GameObject被实例的而并非按照此前提到的通过private constructor的方法生成的单例,我们依然可以利用单例设计中的部分思想来使他调用起来更方便。此后,当我们需要调用GameController中的方法时,只需要调用他的单例即可
GameController.GetInstance().MethodName();
4. 总结
在我学习OOP中常用的设计模式的过程中,我的教授表达了并不推荐学生使用单例设计的看法。他认为单例设计 “破例的使用了全局变量,破坏了模块化设计的思想 ”。但此后,我在学习过程中多次看到其他教授使用单例设计,Github上也有一些不小的项目用到过单例设计;同时,我自己在游戏开发过程中也常常感受到这种设计模式带来的便利。所以,我觉得只要合理运用,单例设计也不失为一种好的设计模式。如有不同意见或者高手有什么指教,欢迎评论。
算法、数据结构、与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design)的更多相关文章
- JAVA设计模式:单例设计
1.单例设计Singleton的引出 单例设计,从名字上首先可以看出单---即只有一个,例---只的是实例化对象:那么单例也就是说一个类,只产生了一个实例化对象.但是我们都知道,一个类要产生实例化对象 ...
- [Unity游戏开发]向量在游戏开发中的应用(三)
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51088236 在上一篇博客中讲了利用向量点乘在游戏开发中应用的几种情景.本 ...
- 【Cocos2d-X游戏实战开发】捕鱼达人之单例对象的设计(二)
本系列学习教程使用的是cocos2d-x-2.1.4(最新版为cocos2d-x-2.1.5) 博主发现前两个系列的学习教程被严重抄袭,在这里呼吁大家请尊重开发者的劳动成果, 转载的时候请务必注 ...
- 借助AMD来解决HTML5游戏开发中的痛点
借助AMD来解决HTML5游戏开发中的痛点 游戏开发的痛点 现在,基于国内流行引擎(LayaAir和Egret)和TypeScript的HTML5游戏开发有诸多痛点: 未采用TypeScript编译器 ...
- [Unity游戏开发]向量在游戏开发中的应用(二)
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/50972976 在上一篇博客中讲了利用向量方向的性质来解决问题.这篇博客将继 ...
- [Unity游戏开发]向量在游戏开发中的应用(一)
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/50810102 向量在游戏开发中是非常实用的,我们在学校学完向量的知识后,只 ...
- Cocos2d-x游戏开发中的消息机制:CCNotificationCenter的使用
在HTML5游戏开发中,js可以使用Event对象的addEventListener(添加事件监听).dispatchEvent(触发事件)实现监听机制,如果在coocos2d-x中,去实现这种机制该 ...
- 二、Cocos2dx概念介绍(游戏开发中不同的坐标系,cocos2dx锚点)
注:ccp是cocos2dx中的一个宏定义,#define ccp(__X__,__Y__)CCPointMake((float)__X__, (float)__Y__),在此文章中表示坐标信息 1. ...
- [C++基金会]位计算 游戏开发中的应用
定义的位操作:通俗点说,,位计算是计算机操作二进制整数. 无论整数可以用二的方式来表示进度,不同类型的其长度的整数位的是不一样的.INT8要么char靠8个月2 位表示,INT16或者short是由1 ...
随机推荐
- 移动端时间回显iphone出现的问题
new Date(item.startTime.replace(/-/g, '/') dateFormat('hh:mm', new Date(item.startTime.replace(/-/g, ...
- Linux 网络分析必备技能:tcpdump 实战详解
大家好,我是肖邦,这是我的第 11 篇原创文章. 今天要分享的是 tcpdump,它是 Linux 系统中特别有用的网络工具,通常用于故障诊断.网络分析,功能非常的强大. 相对于其它 Linux 工具 ...
- SpringBoot配置本地文件映射路径
1.前言 在springboot的项目中,如果需要通过项目方式访问本地磁盘的文件,不仅可以使用nginx代理的方式,还可以使用springboot配置的方式进行访问. 实例原因说明:由于上传的图片是要 ...
- 后端程序员之路 40、Pthreads
POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准.线程这个东西在操作系统原理里讲得比较清楚了,再加上对windows那一套进程线程的东西比较清楚,所以这里还是 ...
- 【转载】Java虚拟机类加载机制与案例分析
出处:https://blog.csdn.net/u013256816/article/details/50829596 https://blog.csdn.net/u013256816/articl ...
- pytorch(03)tensor的操作
张量操作 一.张量的拼接 torch.cat() 功能:将张量按维度dim进行拼接,且[不会扩张张量的维度] tensors:张量序列 dim:要拼接的维度 torch.cat(tensors, di ...
- 番外----python入门----关于pycharm
江湖上有句话叫 "武林至尊,宝刀屠龙,号令天下,莫敢不从,倚天不出,谁与争锋". 今天,我们就来介绍一下,python编程界的"屠龙刀",pycharm. 一. ...
- Nmap命令使用方法
Nmap使用合集 感谢博主:VVVinson 文章链接:https://www.cnblogs.com/Vinson404/p/7784829.html 参 数 说 明 ...
- HDU_3333 Turing Tree 【线段树 + 离散化】
一.题目 Turing Tree 二.分析 这题主要还是在区间的处理上. 为了保证区间内的数没有重复的,那么可以对区间按右端点从小到大排序,这样对原数组处理时,尽量保证不重复的元素靠右(可以假设右端点 ...
- hexo+github 博客绑定域名
关于博客的搭建分为以下几步: 申请域名可以在万维网上申请一个自己的独特域名,本博客的域名即为zhengwei.xyz. 域名解析域名申请成功后继续在万维网上进行操作,进入管理自己的域名界面,在要解析的 ...