游戏编程模式|不要让单例在代码中泛滥

单例模式简述


“确保一个类只有一个实例,并为其提供一个全局访问入口”。
单例模式不仅描述非常简单,代码也非常好写,类似这样:

class Singleton {
public:
    static public Singleton* getInstance(){
        if (instance == NULL){
            instance = new Singleton();
        }
        return instance;
    }
private:
    Singleton(){}
    static Singleton* instance;
}

单例模式确实带给了我们极大的方便,有些情况下,一个类有多个实例就不能正常工作。
比如一个操作文件的类,为了保证各步操作不互相干扰,我们封装的类就必须知道每步调用的操作,如果这个类有多个实例,那么我们就无法获知其他实例的操作。

被玩坏的单例


现在,我学会了一个很好的模式,我一定要在实际编程中使用它~
然后,灾难就来了:我需要一个XXX管理器,在游戏的很多地方都要使用它,对了,使用单例模式就轻松解决了!
于是,在代码中就充满了单例,然而,单例一时爽,却有很多隐患。

虽然有单例模式这种看起来高端一些的名字,实际上,单例模式就是一个全局变量,全局变量的危害许多人都非常了解,但是套上了一层设计模式的面纱,就把它抛之脑后了,美其名曰:我再使用单例模式写代码。但是,随着游戏变得更大更复杂,这样的全局变量就会带来很多危害:

  1. 它们令代码晦涩难懂。假设我们正在跟踪其他人写的函数中的bug。如果这个函数没有使用全局状态,那么我们只需要将精力集中在理解函数体,和传递给它的参数就可以了。
  1. 全局变量促进了耦合。全局变量使得任何人都可以轻松的使用它,在一个不了解结构的新手完成开发任务时,很可能为了完成任务,使得本不应该产生耦合的地方使用了这个单例。
  2. 它对并发不友好。当设置全局变量时,我们创建了一段内存,每个线程都能访问和修改它,而不管它们是否知道其他线程正在操作它。这有可能导致死锁、条件竞争和其他一些难以修复的线程同步的bug。

难以控制的单例


如果你的单例会在需要的时候创建,会出现这样的问题:你无法得知单例创建的时间。

当你实例化一个游戏系统的时候,可能会花费较长的时间,作为用户,肯定不希望在玩游戏玩得正嗨的时候遇到卡顿和掉帧,因此,比较好的方法是在加载游戏的时候手动控制单例的初始化。

你还需要小心翼翼的处理单例初始化的顺序(如果某个单例与另一个单例存在耦合,当然,不存在耦合是最好的,然而,当系统非常庞大的时候,你很难保证这一点),让你的系统能够正常的运行。

LZ在做的游戏中有个读取配置的单例系统,在做另一个单例系统的功能的时候,又依赖这个读取配置的单例。悲剧的是,在退出游戏到登录界面的时候,会把原来的系统干掉,重新读取配置,然而,另一个单例却依然存在,在某些特殊的情况下,调用这个功能的时候,程序就会崩溃掉。
因此,LZ不得不将两个系统的生命周期理顺,在当时临近发版本不能发生大的改动的情况下,只能加上很多check的代码防止崩溃。
虽然这个例子中的情况并不会很常见,但LZ想说的是,这个系统本来就可以不用单例的方式编写,当你能很好的控制这个实例的生命周期的时候,以上出现的各种奇怪的问题就不会出现了。单例用起来简单,可是它会一步一步将你的系统变得更见复杂和难以管理,留下许多暗坑。因此,在你想使用单例的时候,最好想一想,是否一定需要这样处理。

Other


当然,完全不使用单例也不是很现实。单例依然很强大并实用,在使用中,始终保持谨慎是很重要的,在最需要的地方使用,而抛弃那些可有可无的方案,不让单例模式在代码中泛滥,会让程序更加健壮~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容

  • 单例模式(SingletonPattern)一般被认为是最简单、最易理解的设计模式,也因为它的简洁易懂,是项目中最...
    成热了阅读 4,253评论 4 34
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,085评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,652评论 18 139
  • 我就觉得应该有什么大事要发生 头条新闻,成都发声了 审图必须应用BIM,否则不得通过! 好严肃啊,辣么任性? 但是...
    图驴阅读 2,030评论 0 1
  • 2017.6.12 星期一 雨转多云亲子日记 (50) 马上中学考完小学就要考试了,所以孩子们就要加油复习知识了。...
    于泽妈妈阅读 199评论 0 0