设计模式在程序设计中会经常用到,也许你从来没有留意过设计模式,其实你却一直在使用设计模式!cocos2dx中有不少的设计模式,所以从本篇博客开始探讨一下cocos2dx中的设计模式,看看引擎都使用了哪些设计模式,我们今后写代码要怎样使用某种设计模式。本人菜鸟一枚,如果有任何错误还请留言指教,互相探讨。

大家最熟悉的是单例设计模式了吧,在cocos2dx中单例真是不少啊,我们的大导演不就是单例吗,单例设计模式我之前写过一篇博客,这里就不多说了。第二个设计模式是观察者模式,什么是观察者模式,如何实现观察者模式。就是被观察者含有一个数组,里边存放了所有观察者的引用,在被观察者的状态发生改变的时候,通过调用观察者的函数来通知观察者,实现了信息的传递。之前也有一篇博客写了cocos2dx中用来实现观察者模式的事件监听器NotificationCenter,大家可以看看。本篇博客探讨一下二段构建模式,首先第一个问题是什么是二段构建模式。

大家都知道在c++中我们一般在构造函数中为对象分配内存空间然后初始化成员变量,比如我们调用了new某个东西,那么在堆上会先为对象分配内存空间,然后调用构造函数,在构造函数中完成一些初始化的工作。而二段构建模式就是将内存空间的分配和初始化分开来完成,然后调用一个静态方法来返回这个对象。就拿cocos2dx中的Sprite类来说吧,当我们调用Sprite::create()的时候内部先使用new来分配内存空间,然后调用init方法来初始化一些变量的设置。所以cocos2dx中的二段构建模式就是将new分配内存空间和init初始化内容分开来处理,而不是c++传统的做法在构造函数中初始化变量。

1 Sprite* Sprite::create()
2     {
3         //分配内存
4         Sprite *sprite = new Sprite();
5         //init初始化
6         if (sprite && sprite->init())
7         {
8             //内存管理的工作
9             sprite->autorelease();
10             return sprite;
11         }
12         CC_SAFE_DELETE(sprite);
13         return nullptr;
14     }

上边就是使用二段构建模式的过程,Sprite首先调用new来分配内存空间,然后调用init函数来完成初始化的工作,顺带还做了内存管理的工作,最后返回初始化好的对象。所以看了Sprite的create方法的实现,我们也知道了应该怎么使用这个二段构建模式了吧。

第二个问题是为什么要这么用,对于c++程序员来说初始化工作不都是在构造函数中完成的吗,cocos中为何要这么做呢?这里引述一下王哲的话:“其实我们设计二段构造时首先考虑其优势而非兼容cocos2d-iphone. 初始化时会遇到图片资源不存在等异常,而C++构造函数无返回值,只能用try-catch来处理异常,启用try-catch会使编译后二进制文件大不少,故需要init返回bool值。Symbian, Bada SDK,objc的alloc + init也都是二阶段构造”。现在大家明白了吧,兼容cocos2d-iphone是一个原因,另一个重要的原因是构造函数没有返回值啊,如果加载资源图片的时候不存在怎么办,所以初始化的工作写在init函数中,这个函数返回的bool值用来判断是否初始化成功。使用这种方法还可以强化设计,想想自己写代码的时候是不是因为没有初始化某个成员变量导致了bug,这样做就是提醒你记得要在init中初始化成员变量。通过create静态函数返回的这个对象也实现了cocos2dx中的内存管理,就不用我们自己麻烦了。还有一个原因是在c++的构造函数中是不能调用虚函数的,为了调用虚函数来完成一些功能就要写在init函数中。

以上就是二段构建模式的说明了,在我们写cocos程序的时候其实不知不觉就已经在使用这个构建模式了,想一下我们一个类继承了Layer,然后使用了宏CREATE_FUNC(),这不就是create静态方法吗,在init函数中完成了初始化,整个过程就是在用这种设计模式!

设计模式——工厂模式

cocos2dx中也有工厂模式,何为工厂模式,顾名思义就是用来产生产品的,工厂就是用来创建其他类对象的类,我们把这个创建其他类对象的类叫做工厂类,而这些被创建的对象叫做产品,所以这种模式才叫做工厂模式,是不是很形象。我们从纯c++的角度来看一下如何使用工厂模式。工厂模式又分为简单工厂模式、工厂方法模式、抽象工厂模式,先来看一下简单工厂模式如何实现。

简单工厂模式:当在程序中创建对象的时候少不了new,有时候new会很多,又分布在程序的不同地方,管理起来很不方便,这个时候需要一个工厂类,专门负责对象的创建和释放,将对象的这种操作统一在一起,同时工厂类向外部提供了创建对象的接口,而对对象的使用则和这个工厂类毫无关系。

1 #ifndef _FACTORY_H_
2 #define _FACTORY_H_
3 #include <iostream>
4  
5 using namespace std;
6  
7 enum ProductType
8 {
9     typeA,
10     typeB
11 };
12  
13 //产品类的基类
14 class Product
15 {
16 public:
17     //存虚函数
18     virtual void show()=0;
19 };
20  
21 class ProductA : public Product
22 {
23 public:
24     void show()
25     {
26         cout<<"ProductA\n";
27     };
28 };
29  
30 class ProductB : public Product
31 {
32 public:
33     void show()
34     {
35         cout<<"ProductB\n";
36     };
37 };
38  
39 //工厂类,用来产生产品
40 class Factory
41 {
42 public:
43     //根据传入的不同产品类型产生不同的对象
44     Product * createProduct(ProductType type)
45     {
46         switch(type)
47         {
48         case typeA:
49             return new ProductA();
50         case typeB:
51             return new ProductB();
52         default:
53             return NULL;
54         }
55     };
56 };
57  
58 #endif
1 #include "Factory.h"
2  
3 int main()
4 {
5     Factory * factory = new Factory();
6     //产生产品
7     ProductA * pa = (ProductA *)factory->createProduct(typeA);
8     pa->show();
9  
10     ProductB * pb = (ProductB *)factory->createProduct(typeB);
11     pb->show();
12  
13     //记得析构
14     delete factory;
15     //产品的析构可以放到factory类的析构函数中去做
16     delete pa;
17     delete pb;
18  
19     return 0;
20 }

设计模式——工厂模式

工厂方法模式:是为了解决简单工厂模式的弊端存在的,简单工厂模式的扩展性不好,比如我们有了第三个产品ProductC,我们需要工厂为我们产生这个对象,怎么办,需要修改工厂类中的创建对象的函数,也就是switch结构,还有就是枚举处也要进行修改,而这种修改会带来不少的弊端,所以我们就有了工厂方法模式。这个模式将Factory设计为抽象类,其中包含子类必须实现的方法,而对产品的具体创建则放到Factory的子类中去完成。这个时候如果有一个产品C,我们就创建一个工厂类FactoryC,专门用来产生产品C,就不需要改动其他地方的代码了。

1 #ifndef _FACTORY_H_
2 #define _FACTORY_H_
3 #include <iostream>
4  
5 using namespace std;
6  
7 //产品类的基类
8 class Product
9 {
10 public:
11     //存虚函数
12     virtual void show()=0;
13 };
14  
15 class ProductA : public Product
16 {
17 public:
18     void show()
19     {
20         cout<<"ProductA\n";
21     };
22 };
23  
24 class ProductB : public Product
25 {
26 public:
27     void show()
28     {
29         cout<<"ProductB\n";
30     };
31 };
32  
33 //工厂抽象类,定义子类必须实现的接口
34 class Factory
35 {
36 public:
37     //根据传入的不同产品类型产生不同的对象
38     virtual Product * createProduct()=0;
39 };
40  
41 //具体的工厂类,用来产生不同的产品
42 class FactoryA : public Factory
43 {
44 public:
45     Product * createProduct()
46     {
47         return new ProductA();
48     };
49 };
50  
51 class FactoryB : public Factory
52 {
53 public:
54     Product * createProduct()
55     {
56         return new ProductB();
57     };
58 };
59  
60 #endif
1 #include "Factory.h"
2  
3 int main()
4 {
5     //产生产品
6     FactoryA * factoryA = new FactoryA();
7     Product * pa = factoryA->createProduct();
8     pa->show();
9  
10     FactoryB * factoryB = new FactoryB();
11     Product * pb = factoryB->createProduct();
12     pb->show();
13  
14     //记得析构
15     delete factoryA;
16     delete factoryB;
17     //产品的析构可以放到factory类的析构函数中去做
18     delete pa;
19     delete pb;
20  
21     return 0;
22 }

设计模式——工厂模式

设计模式——工厂模式

抽象工厂模式:现在我们的产品类都是继承自Product的,如果有一个产品不是Product的子类怎么办呢?这个时候就用到了抽象工厂模式,这个模式是工厂方法模式的叠加,其他的东西类似,看下代码就清楚了。

1 #ifndef _FACTORY_H_
2 #define _FACTORY_H_
3 #include <iostream>
4  
5 using namespace std;
6  
7 //产品类A类的基类
8 class ProductA
9 {
10 public:
11     //存虚函数
12     virtual void show()=0;
13 };
14  
15 class ProductA1 : public ProductA
16 {
17 public:
18     void show()
19     {
20         cout<<"ProductA1\n";
21     };
22 };
23  
24 class ProductA2 : public ProductA
25 {
26 public:
27     void show()
28     {
29         cout<<"ProductA2\n";
30     };
31 };
32  
33 //产品类B类的基类
34 class ProductB
35 {
36     virtual void show()=0;
37 };