Cocos2D-X 设计模式:二段构建模式

本文介绍Cocos2d-x中的二段构建模式,该模式将对象构建分为内存分配与初始化两个阶段,并通过静态工厂方法实现。探讨了此模式的历史背景、优势与应用场景。

本文转自子龙山人的博客:http://4gamers.cn/archives/88


乍一看标题,大家可能会觉得很奇怪,神马是“二段构建模式”呢?

所谓二段构建,就是指创建对象时不是直接通过构建函数来分配内存并完成初始化操作。取而代之的是,构造函数只负责分配内存,而初始化的工作则由一些名为initXXX的成员方法来完成。然后再定义一些静态类方法把这两个阶段组合起来,完成最终对象的构建。因为在《Cocoa设计模式》一书中,把此惯用法称之为“Two Stage Creation”,即“二段构建”。

2014.6.1号更新:

1.应用场景:

二段构建在cocos2d-x里面随处可见,自从3.0版本以后,所有的二段构建方法的签名都改成create了。这样做的好处是一方面统一接口,方便记忆,另一方面是以前的类似Cocoa的命名规范不适用c++,容易引起歧义。下面以Sprite为类,来具体阐述二段构建的过程,请看下列代码:

如上面代码中的注释所示,创建一个sprite明显被分为两个步骤:1.使用new来创建内存;2.使用initXXX方法来完成初始化。

因为Sprite的构造函数也有初始化的功能,所以,我们再来看看Sprite的构建函数实现:

很明显,这个构建函数所做的初始化工作非常有限,仅仅是在初始化列表里面初始化了m_pobTexture和m_bShouldBeHidden两个变量。实际的初始化工作大部分都放在initXXX系列方法中,大家可以动手去查看源代码。

2.分析为什么要使用此模式?

这种二段构建对于C++程序员来说,其实有点别扭。因为c++的构造函数在设计之初就是用来分配内存+初始化对象的。如果再搞个二段构建,实则是多此一举。但是,在objective-c里面是没有构造函数这一说的,所以,在Cocoa的编程世界里,二段构建被广泛采用。而cocos2d-x当初是从cocos2d-iphone移植过来了,为了保持最大限度的代码一致性,所以保留了这种二段构建方式。这样可以方便移植cocos2d-iphone的游戏,同时也方便cocos2d-iphone的程序员快速上手cocos2d-x。

不过在后来,由于c++天生不具备oc那种可以指定每一个参数的名称的能力,所以,cocos2d-x的设计者决定使用c++的函数重载来解决这个问题。这也是后来为什么2.0版本以后,都使用create函数的重载版本了。

虽然接口签名改掉了,但是本质并没有变化,还是使用的二段构建。二段构建并没有什么不好,只是更加突出了对象需要初始化。在某种程度上也可以说是一种设计强化。因为忘记初始化是一切莫名其妙的bug的罪魁祸首。同时,二段构建出来的对象都是autorelease的对象,而autorelease对象是使用引用计数来管理内存的。客户端程序员在使用此接口创建对象的时候,无需关心具体实现细节,只要知道使用create方法可以创建并初始化一个自动释放内存的对象即可。

在一点,在《Effective Java》一书中,也有提到。为每一个类提供一个静态工厂方法来代替构造函数,它有以下三个优点:

  • 与构造函数不同,静态方法有名字,而构造函数只能通过参数重载。

  • 它每次被调用的时候,不一定都创建一个新的对象。比如boolean.valueof(boolean)。

  • 它还可以返回原类型的子类型对象。

因此,使用二段构建的原因有如下几点:- 兼容性、历史遗留原因。(这也再次印证了一句话,一切系统都是遗留系统,呵呵)

  • 二段构建有其自身独有的优势。

  • 构造函数执行期间是不能调用virtual函数的(即使调用了virtual,编译器也会用静态调用机制而不是virtual机制,详见Effective C++条款9),如果不用二段建构方式,在基类的构造函数里就不能调用virtual函数实现子类需要定制化的功能,比如当需要采用模板方法这样的设计模式做初始化的时候。但如果使用二段建构,就可以把这部分放在init()里,实现了初始化时使用模板方法的方式。构造函数里无法通过irtual函数实现虚函数机制,但init函数调用的时候,就可以调用virtual函数了(感谢nichos)

  • 如果在构造函数中调用可能异常退出的函数,那么当异常发生,函数调用栈马上弹出,直到找到try cathc为止。也就是说分配出的内存来不急释放(在构造函数里发生异常,甚至连分配出的内存指针都拿不到),函数执行就中止了。进行两段构造可以提供一个进行try catch的机会,Symbian的两段构造+清除栈的处理方式比这里提到的策略安全的多。(感谢omega)

3.使用此模式的优缺点是什么?

优点:

  • 显示分开内存分配和初始化阶段,让初始化地位突出。因为程序员一般不会忘记分配内存,但却常常忽略初始化的作用。

  • 见上面分析《Effective Java》的第1条:“为每一个类提供一个静态工厂方法来代替构造函数”

  • 除了完成对象构建,还可以管理对象内存。

缺点:

  • 1.不如直接使用构造函数来得直白、明了,违反直觉,但这个是相对的。

4.此模式的定义及一般实现

定义:将一个对象的构建分为两个步骤来进行:1.分配内存 2.初始化它的一般实现如下:

5.在游戏开发中如何运用此模式

这个也非常简单,就是今后在使用cocos2d-x的时候,如果你继承Sprite实现自定义的精灵,你也需要按照“二段构建”的方式,为你的类提供一个静态工厂方法,同时编写相应的初始化方法。当然,命名规范最好和cocos2d-x统一,即静态工厂方法为create,而初始化方法为initXXXX。

6.此模式经常与哪些模式配合使用

由于此模式在GoF的设计模式中并未出现,所以暂时不讨论与其它模式的关系。

最后看看cocos2d-x创始人王哲对于为什么要设计成二段构建的看法:

“其实我们设计二段构造时首先考虑其优势而非兼容cocos2d-iphone. 初始化时会遇到图片资源不存在等异常,而C++构造函数无返回值,只能用try-catch来处理异常,启用try-catch会使编译后二进制文件大不少,故需要init返回bool值。Symbian, Bada SDK,objc的alloc + init也都是二阶段构造”。

欢迎读者批评指正,


基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)内容概要:本文档围绕基于遗传算法的异构分布式系统任务调度算法展开研究,重点介绍了一种结合遗传算法的新颖优化方法,并通过Matlab代码实现验证其在复杂调度问题中的有效性。文中还涵盖了多种智能优化算法在生产调度、经济调度、车间调度、无人机路径规划、微电网优化等领域的应用案例,展示了从理论建模到仿真实现的完整流程。此外,文档系统梳理了智能优化、机器学习、路径规划、电力系统管理等多个科研方向的技术体系与实际应用场景,强调“借力”工具与创新思维在科研中的重要性。; 适合人群:具备一定Matlab编程基础,从事智能优化、自动化、电力系统、控制工程等相关领域研究的研究生及科研人员,尤其适合正在开展调度优化、路径规划或算法改进类课题的研究者; 使用场景及目标:①学习遗传算法及其他智能优化算法(如粒子群、蜣螂优化、NSGA等)在任务调度中的设计与实现;②掌握Matlab/Simulink在科研仿真中的综合应用;③获取多领域(如微电网、无人机、车间调度)的算法复现与创新思路; 阅读建议:建议按目录顺序系统浏览,重点关注算法原理与代码实现的对应关系,结合提供的网盘资源下载完整代码进行调试与复现,同时注重从已有案例中提炼可迁移的科研方法与创新路径。
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)内容概要:本文提出了一种基于非支配排序的蜣螂优化算法(NSDBO),用于求解微电网多目标优化调度问题。该方法结合非支配排序机制,提升了传统蜣螂优化算法在处理多目标问题时的收敛性和分布性,有效解决了微电网调度中经济成本、碳排放、能源利用率等多个相互冲突目标的优化难题。研究构建了包含风、光、储能等多种分布式能源的微电网模型,并通过Matlab代码实现算法仿真,验证了NSDBO在寻找帕累托最优解集方面的优越性能,相较于其他多目标优化算法表现出更强的搜索能力和稳定性。; 适合人群:具备一定电力系统或优化算法基础,从事新能源、微电网、智能优化等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网能量管理系统的多目标优化调度设计;②作为新型智能优化算法的研究与改进基础,用于解决复杂的多目标工程优化问题;③帮助理解非支配排序机制在进化算法中的集成方法及其在实际系统中的仿真实现。; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注非支配排序、拥挤度计算和蜣螂行为模拟的结合方式,并可通过替换目标函数或系统参数进行扩展实验,以掌握算法的适应性与调参技巧。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值