学习cocos2d-x的过程中,会发现很多对象都通过一个静态函数create来创建。比方以下的一个样例

#define CREATE_FUNC (__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL ; \
} \
}

查看源码能够知道这里有一个通用的create函数,它基本的功能是创建实例。通过new实现。然后进行初始化,通过init()来实现,并加入一个autorelease()来实现回收机制。一開始认为挺别扭,由于构造函数本来就是用于创建并初始化实例的。这样做有点多此一举。或者是一种代码风格,不能理解。上网查完之后才知道原来这样的风格有一个名字叫做二段构造模式。

cocos2d-x的作者王哲对于这个问题的解答是“事实上我们设计二段构造时首先考虑其优势而非兼容cocos2d-iphone. 初始化时会遇到图片资源不存在等异常,而C++构造函数无返回值,仅仅能用try-catch来处理异常,启用try-catch会使编译后二进制文件大不少,故须要init返回bool值。

Symbian,
Bada SDK,objc的alloc + init也都是二阶段构造”。把分配内存与初始化分开,有利于调试初始化出现的一些问题。

而构造函数把内存分配和初始化一并完毕,难以把两种阶段分离开来。给调试带来一定的不便。除了这个初衷,应该有一部分原因是由于cocos2d-x是由cocos2d-iphone衍生而来,为了保持代码风格一致,而留下这样的创建对象的方式。(由于object-c中是没有构造函数这样的概念)。同一时候也方便代码移植到iPhone平台上,并且也方便-x和-iphone的程序猿可以迅速转换吧。

看了子龙山人一文《Cocos2d-x设计模式发掘之二:二段构造模式》,更是进一步了解到事实上这样的方法把内存分配与初始化分离,能够说是一种设计强化。由于我们往往在创建对象后忘记初始化。这样的bug常常发生。如今二段构造的模式强调了初始化工作。

讲到这里,事实上才发现这个问题的本质是构造函数和静态工厂方法两种方式创建对象的比較。

採用构造函数实例化对象是语言的规范。用这样的方法比較直观

而採用静态工厂方法则有下面3个有点:(參考http://blog.csdn.net/cgwshxs/article/details/3455136)

1、构造方法的名字必须与类名同样。而静态工厂方法的方法名能够是随意的,这一特性的长处是能够提高程序代码的可读性。在方法名中能体现与实例有关的信息。

2、每次运行new语句时,都会创建一个新的对象。而静态工厂方法每次被调用的时候,是否会创建一个新的对象全然取决于方法的实现。

3、静态工厂方法能够返回当前类的子类的实例。这一特性能够在创建松耦合的系统接口时发挥作用。

尽管静态工厂方法有这些长处。可是当对象的构造方法是私有或者default时,这样的方法就不能创建该对象了。并且静态工厂方法和其它静态方法从名字上看无法区分。

在通常的情况下,利用构造函数还是最直接的方法,可是当条件同意,使用静态工厂方法也是明智之举。

就如在《Effivtive JAVA》一书中推荐的一样,为每个类提供一个静态工厂方法来取代构造函数。

    

  

cocos2d-x中的二段构造模式的更多相关文章

  1. 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  2. 设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)

    今天是五.四青年节,祝大家节日快乐.看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火.这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知 ...

  3. Android中的创建型模式总结

    共5种,单例模式.工厂方法模式.抽象工厂模式.建造者模式.原型模式 单例模式 定义:确保某一个类的实例只有一个,而且向其他类提供这个实例. 单例模式的使用场景:某个类的创建需要消耗大量资源,new一个 ...

  4. MVC中使用泛型仓储模式和依赖注入

    在ASP.NET MVC中使用泛型仓储模式和依赖注入,实现增删查改 原文链接:http://www.codeproject.com/Articles/838097/CRUD-Operations-Us ...

  5. C++之二阶构造模式

    前言:C++中经常会因为调用系统资源失败导致出现BUG,所以在类调用构造函数需要分配系统资源时会出现BUG,从而导致类对象虽然被创建,但是只是个半成品,为了避免这种情况需要使用二阶构造模式 二阶构造模 ...

  6. C++解析(15):二阶构造模式

    0.目录 1.构造函数与半成品对象 2.二阶构造 3.小结 1.构造函数与半成品对象 关于构造函数: 类的构造函数用于对象的初始化 构造函数与类同名并且没有返回值 构造函数在对象定义时自动被调用 问题 ...

  7. 在C++11中实现监听者模式

    参考文章:https://coderwall.com/p/u4w9ra/implementing-signals-in-c-11 最近在完成C++大作业时,碰到了监听者模式的需求. 尽管C++下也可以 ...

  8. 【转】Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式

    [转]Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式 博客分类: 企业应用面临的问题 java并发编程 Struts2的线程安全ThreadLocal模式St ...

  9. 在MVC中使用泛型仓储模式和依赖注入实现增删查改

    标签: 原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository ...

随机推荐

  1. Sublime 插件Pylinter could not automatically determined the path to lint.py

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50618630 安装Sublime Te ...

  2. Maven中的parent定义的dependency,其中继承者是可以直接使用parent中的Maven Dependencies的。

    Maven中的parent定义的dependency,其中继承者是可以直接使用parent中的Maven Dependencies的. packagin要选择jar,parent project要选择 ...

  3. httpclient就是个能发送http连接的工具包,包括能发送post请求和get请求

    1.httpclient就是个能发送http连接的工具包,包括能发送post请求和get请求. http 连接一次就有返回流.http是个双向的嘛.只有连接了,就会有输出返回流. 所以在执行http连 ...

  4. 12:打印 1 到最大的 n 位数

    题目:输入数字 n.按顺序打印出从 1 到 最大的 n 位十进制数.比方输入 3 ,则打印出 1.2 .3 一直到最大的3位数即 999. 解析: easy知道不能用 int 等数字类型表示(大数问题 ...

  5. 【剑指offer】Q31:连续子数组的组大和

    简短的分析见:http://blog.csdn.net/shiquxinkong/article/details/17934747 def FindGreatestSumOfSubArray(arra ...

  6. poj3249 Test for job 【图的DAG dp】

    #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> ...

  7. 高速排序算法C++实现

    //quick sort //STL中也有现成的高速排序算法.内部实现採用了下面技巧 //1)枢轴的选择採取三数取中的方式 //2)后半段採取循环的方式实现 //3)高速排序与插入排序结合 #incl ...

  8. Wireshark默认不抓取本地包的解决方式

    事实上这个工具我已经用过非常多年了,还叫Ethereal的时候就在用. 今天因为实验须要,要抓一下在localhost间的包,结果发现获取不到.解决方法也非常easy,在cmd下输入: route a ...

  9. 《Head First 设计模式》学习笔记——适配器模式 + 外观模式

    在ADO.NET中.对于我们从数据库中取出的数据都要放到一个DataSet中,无论你是Access的数据库,还是SQL的数据库,或者是Oracle的数据库都要放到DataSet中..NET中并没有提供 ...

  10. m_Orchestrate learning system---二十、如何写代码不容易犯错

    m_Orchestrate learning system---二十.如何写代码不容易犯错 一.总结 一句话总结:能排序多排序 这次查错的启示: 1.代码数据更规整:要是取出的数据排序的话可以减少很多 ...