展会信息港展会大全

由Cocos2d-x工程入口窥见代理模式
来源:互联网   发布日期:2015-09-28 10:58:22   浏览:1215次  

导读: 关于设计模式(Design Pattern),自从“四人帮”第一次在《Design Patterns: Elements of Reusable Object-Oriented Softwar...

关于设计模式(Design Pattern),自从“四人帮”第一次在《Design Patterns: Elements of Reusable Object-Oriented Software》中将其上升到理论高度,发展到今天已经成为众所周知的代码设计经验的总结。然而,关于设计模式的具体使用,大多数人却望而生畏,具体原因在于:书上提及的理论往往过于晦涩,读者只见其结果,却不明白这样设计的动机与过程;即,缺乏大型项目实践的支撑,或者说,没有经历一个数十万行项目的迭代、开发、重构,确实难以理解设计模式的智慧。

自然,笔者也不敢说有多懂设计模式,只是从一些开源的项目中看见些许设计模式的影子,本文打算不做过多的理论讲解,而是直接从Cocos2d-x工程入口的代码部分尝试与大家分享其中体现的代理模式。注:笔者使用的Cocos2d-x版本为2.2.6,不能保证3.X版本一样适用。

先建立一个最简单的Hello World项目(具体过程不做阐述,网上可以查看教程),我们找到main函数,代码如下:

1 int APIENTRY _tWinMain(HINSTANCE hInstance,

2HINSTANCE hPrevInstance,

3LPTSTRlpCmdLine,

4intnCmdShow)

5 {

6UNREFERENCED_PARAMETER(hPrevInstance);

7UNREFERENCED_PARAMETER(lpCmdLine);

8

9// create the application instance

10AppDelegate app;

11CCEGLView* eglView = CCEGLView::sharedOpenGLView();

12eglView->setViewName("Hello World");

13eglView->setFrameSize(480, 320);

14return CCApplication::sharedApplication()->run();

15 }

从 AppDelegate app; 我们看出这是一个代理模式,查看其定义我们看到 class AppDelegate : private cocos2d::CCApplication ,即继承自CCApplication类。我们先放在一边,继续往下看。

显然,想要从main函数跳到工程的入口是从 CCApplication::sharedApplication()->run() 这句代码实现的。其中sharedApplication()是一个单例模式,其内部有一个静态指针,指针为空则创建对象,不为空则跳过,如此设定以保证多次调用仍然只返回唯一一个单例。当然本文不是讲解单例模式,简单提及一下。下面我们转入CCApplication的定义,找到如下代码:

1// Initialize instance and cocos2d.

2if (!applicationDidFinishLaunching())

3{

4return 0;

5}

显然,这里便是整个游戏工程的入口。我们考虑,该函数在何处定义?如果 applicationDidFinishLaunching() 是CCApplication类中的成员函数,我们便可以直接调用而无需顾虑。而事实是这样吗?我们转入其定义。看到 bool AppDelegate::applicationDidFinishLaunching() 这样的代码。即,真正的实现是在AppDelegate中完成的。然而,我们发现,在CCApplication类中既无定义,也无声明,那为什么可以使用?我们看CCApplication类,看到 class CC_DLL CCApplication : public CCApplicationProtocol 这句话,即它是继承子CCApplicationProtocol。再次跳转到该函数的定义,我们看到 virtual bool applicationDidFinishLaunching() = 0; ,这是一个纯虚函数。何为纯虚函数?纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。在派生类中,若未对该接口进行复写(OverRide),该派生类依然为纯虚基类。显然,在CCApplication类中并没有进行复写,却可以直接调用该接口。

回到最上面,我们知道AppDelegate继承自CCApplication类,在AppDelegate中给出了该函数的定义 virtual bool applicationDidFinishLaunching(); ,这不是一个纯虚函数,即,可以对其进行实现。

回顾一下逻辑,整理如下:

1 #if 0

8 CCApplicationProtocol //Interface

9virtual bool applicationDidFinishLaunching() = 0; //定义一个纯虚函数的接口

10

11 //各个平台不同的逻辑

12 CCApplication: public CCApplicationProtocol

13run()

14{

15applicationDidFinishLaunching(); //调用该接口

16}

17

18 AppDelegate: private CCApplication

19applicationDidFinishLaunching() //实现接口

20{

21真正的入口;

22}

23

24virtual bool applicationDidFinishLaunching();

25

26virtual void applicationDidEnterBackground();

27

28virtual void applicationWillEnterForeground();

29

30 #endif

关于代理模式的优点:

职责清晰,真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。

代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。

高扩展性

好了,本文到此就要结束了,通过一个具体的工程案例,希望大家对代理模式能学到一些新的内容。关于理论部分就不多做阐述,大家可以去看看《设计模式》这本书。

赞助本站

人工智能实验室
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港