[cocos2dx]Delegate委托设计模式

实现委托机制demo的情景描述:
LayerA是一个层,里面有个sprite,一旦A被初始化,这个sprite就会执行一个action;LayerB是另一个层。我在LayerB中加入了LayerA,但是要等到A中的那个sprite的action执行完毕后,B再立刻执行另外一个方法。
问题来了,我怎么在LayerB中知道LayerA中的sprite的action执行完了,那么解决的方法就是使用委托机制。

//首先创建一个VirtualClassC类,里面有一个虚函数。
class VirtualClassC
{
public:
    //虚函数
    virtual void actionFinished(){};
};

LayerA

接着创建LayerA,这个类继承CCLayer,并且有一个VirtualClassC类实例。

//**********************LayerA.h文件***************************

#ifndef __delegate__LayerA__
#define __delegate__LayerA__
 
#include <iostream>
#include "VirtualClassC.h"
#include "cocos2d.h"
USING_NS_CC;
 
class LayerA :public CCLayer
{
public:
    virtual bool init();
    CREATE_FUNC(LayerA);
    
    VirtualClassC *delegate_;
    
    void callBack();
};
 
#endif /* defined(__delegate__LayerA__) */


//************************LayerA.cpp文件*************************

#include "LayerA.h"
 
bool LayerA::init()
{
    if (!CCLayer::init()) {
        return false;
    }
    
    //在LayerA层中添加一个sprite
    CCSprite *pSprite = CCSprite::create("Icon.png");
    CCSize wSize = CCDirector::sharedDirector()->getWinSize();
    pSprite->cocos2d::CCNode::setPosition(wSize.width/2, wSize.height/2);
    this->addChild(pSprite);
    
    //让这个sprite执行一个动作序列
    
    CCSequence *action = CCSequence::create(CCRotateBy::create(0.5, 360),CCCallFunc::create(this, callfunc_selector(LayerA::callBack)),NULL);
    pSprite->runAction(action);
    
    return true;
}
 
void LayerA::callBack()
{
    if (delegate_) {
        delegate_->actionFinished();
    }
}

LayerB

这个类继承 VirtualClassC类和CCLayer类。

//***********************LayerB.h文件**************************

#ifndef __delegate__LayerB__
#define __delegate__LayerB__
 
#include <iostream>
#include "VirtualClassC.h"
#include "LayerA.h"
#include "cocos2d.h"
USING_NS_CC;
 
//
class LayerB:public VirtualClassC,public CCLayer
{
public:
    virtual bool init();
    static cocos2d::CCScene* scene();
    
    CREATE_FUNC(LayerB);
    
    virtual void actionFinished();
    
    //假如A中action完毕后,B要去执行下面的方法
    void doNext();
};
 
#endif /* defined(__delegate__LayerB__) */


//************************LayerB.cpp文件*************************

#include "LayerB.h"
 
bool LayerB::init()
{
    if ( !CCLayer::init() )
    {
        return false;
    }
    
    CCSize wSize = CCDirector::sharedDirector()->getWinSize();
    
    LayerA *layerA = LayerA::create();
    layerA->delegate_ = this;
    layerA->setPosition(0, 0);
    this->addChild(layerA);
    
    CCLabelTTF *label = CCLabelTTF::create("LayerB", "Arial", 24);
    label->setPosition(ccp(wSize.width/2, 80));
    this->addChild(label);
    
    return true;
}
 
CCScene* LayerB::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    LayerB *layer = LayerB::create();
    
    // add layer as a child to scene
    scene->addChild(layer);
    
    // return the scene
    return scene;
}
 
void LayerB::actionFinished()
{
    doNext();
}
 
void LayerB::doNext()
{
    CCLog("LayerA中sprite的acton已经结束");
}

在程序启动的时候

    // create a scene. it's an autorelease object
    CCScene *pScene = LayerB::scene();
 
    // run
    pDirector->runWithScene(pScene);

显然,程序运行的效果是,LayerA中的sprite执行一个旋转动作后,LayerB就会执行doNext方法,在终端中输出
"LayerA中sprite的acton已经结束"。


下面对于这个委托机制解释一下

  1. VirtualClassC类中定义了一个虚函数,这个函数相当于就是委托方法;
  2. LayerB继承了这个类,那么就要实现这个类中的虚函数,也即实现了委托方法;
  3. LayerA中定义了一个VirtualClassC类实例,而且在LayerB的init方法中:layerA->delegate_ =this;即将LayerA中的委托对象指定为LayerB。

委托实现再理解:函数调用时,发生动态绑定。
我们知道:基类类型的指针或引用可以指向或引用基类类型对象,或者派生类类型对象。
那么:
1、通过基类类型指针或者引用指向了派生类对象,然后对函数调用
2、所调用函数为虚函数,派生类重写了该虚函数。
这个时候会发生的函数调用是在运行期间才知道的,调用的不是基类版本的函数,而是派生类中的函数,所以是动态绑定。这就是动态多态性了。(静态多态性是函数重载)

在这个例子中:                                                          

  1. 首先定义一个基类VirtualClassC,其中有一个虚函数(基类相当于一个委托协议,虚函数相当于委托方法,但还未实现);
  2. 然后 LayerA 有一个该基类 VirtualClassC 的实例指针(public),使用这个指针调用VirtualClassC 中的虚函数,即调用委托方法(LayerA 相当于委托者,基类实例指针相当于委托实例,委托实例调用委托方法);
  3. 最后 LayerB 继承基类VirtualClassC,成为其子类,重写虚函数,并且创建 LayerA 实例,将 LayerA 中的 VirtualClassC 实例指针指向自己(this)(LayerB 相当于被委托者,需要实现委托方法)。
  4. 这样的效果是:在 LayerA 中 VirtualClassC 实例调用的是 LayerB 中重写的虚函数(委托方法)。这样就完成了委托的过程。

其实就是你要设计一些可重用的组件,或者有些行为在编译的时候无法确定,需要根据运行时环境指定,也可以采用委托。其实说白了,也就是对象组合+针对接口编程的产物。如果遵守了这些良好的设计原则,你的软件系统之中到处可以见到委托的缩影。
委托还是两个对象之间通信的一种方式。为什么不直接通信呢?因为解耦嘛,你懂的。
委托模式与观察者和策略模式有着千丝万缕的联系.

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页