学习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. maven小知识点

    Maven 使用惯例优于配置的原则 .它要求在没有定制之前,所有的项目都有如下的结构: 一个 maven 项目在默认情况下会产生 JAR 文件,另外 ,编译后 的 classes 会放在 basedi ...

  2. 为什么选性别会导致兴趣都选中-vue

    为什么选性别会导致兴趣都选中-vue <%@ page language="java" import="java.util.*" pageEncoding ...

  3. POJ 2041 Unreliable Message

    简单模拟.依照题意处理一下字符串就可以. 应该是写题号写错了,本来我在VirtualJudge是加入的POJ 并查集与生成树的题. #include<cstdio> #include< ...

  4. 设计网页录入信息与自己定义server数据接收

    需求:设计一个注冊网页用于录入username和登录password.并将数据传入server并显示出来. 1.前言:网页提交的 get 和 post 两种方式. (1)对于get提交方式,以本文中样 ...

  5. 数据挖掘算法学习(四)PCA算法

    转载请附上链接http://blog.csdn.net/iemyxie/article/details/38236647 算法简单介绍 主成分分析(PrincipalComponentAnalysis ...

  6. POJ 2318 叉积判断点与直线位置

    TOYS   Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom ...

  7. iOS开发—在@interface,@implementation和@property中变量的定义

    一直搞不懂在OC中变量在@interface和@implementation中有什么区别,定义@property又有什么不同,查了很多资料,总结如下: //ViewController.h @inte ...

  8. tf.placeholder类似函数中的形参

    tf.placeholder(dtype, shape=None, name=None) 此函数可以理解为形参,用于定义过程,在执行的时候再赋具体的值 参数: dtype:数据类型.常用的是tf.fl ...

  9. Java数据库连接——PreparedStatement的使用

    首先了解Statement和PreparedStatement的区别: 由此可见,一般使用PreparedStatement. 操作数据库SU(Course表),其中Course属性有Cno,Cnam ...

  10. C# 分隔字符串成为字符串数组的方法(保留分隔符)

    要求如下: source string: mmmmmmynameismickeym separator: m result string []: {"m", "m&quo ...