学习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. 【codeforces 794B】Cutting Carrot

    [题目链接]:http://codeforces.com/contest/794/problem/B [题意] 给你一个等腰三角形; 它的底边为1; 高为h; 要求你把这个等腰三角形分成n份面积相等的 ...

  2. 【codeforces 508E】Artur and Brackets

    [题目链接]:http://codeforces.com/problemset/problem/508/E [题意] 让你构造一个括号字符串; 使得每个从左往右数第i个左括号在这个括号序列中与之匹配的 ...

  3. WinServer-IIS初始安装及发布网站

    \aspnet_regiis.exe –i 还有非常重要的一步就是给发布文件夹设置权限,到底设置那一个用户的权限我也没有弄清楚,大概是IIS_IUSERS或者IUSR用户就可以了,我设置完了之后没有反 ...

  4. linux svn命令具体解释

    检測是否安装svn:svnserve --version svn服务的关闭:killall svnserve 创建svn库:svnadmin create /opt/svn/repos 配置自己主动启 ...

  5. 用自定义的函数将gps转换为高德坐标

    <?php echo<<<_END <!doctype html> <html> <head> <meta charset=" ...

  6. bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置 (黑白染色+最小割)

    bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置 题目:传送门 简要题意: 和n皇后问题差不多,但是这里是每个棋子走日子,而且有些格子不能放棋子.求最多能放多少个棋 ...

  7. SVG 贝塞尔曲线控制【方便设置】:贝塞尔曲线

    http://dayu.pw/svgcontrol/

  8. mybatis与spring整合配置

    mybatis与spring整合配置: 第一种方式:(此处配置扫描的包路径.注解.每个mapper类上面需要加@Repository才能纳入spring的bean管理器中) <!-- 自动扫描m ...

  9. Core Java(二)

    二 .JAVA语言基础 1.注释,标识符,关键字  Comments         用于解释说明程序的文字 Java中注释分类格式 单行注释:格式: //注释文字                多行 ...

  10. 「JavaSE 重新出发」02.02 引用数据类型

    引用(复合)数据类型 1. 枚举类型 例: 枚举类型 Size 的声明: enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE }; 声明 Size 类型变量: ...