callback pattern

c回调函数与C++回调类

常用回调方法:

  • 第一种Callback的方法是面向过程的,使用简单而且灵活,正如C语言本身。
  • 第二种Sink的方法是面向对象的,在C++里使用较多, 可以在一个Sink里封装一组回调接口,适用于一系列比较固定的回调事件。
  • 第三种Delegate的方法也是面向对象的,和Sink封装一组接口不同,Delegate的封装是以函数为单位,粒度比Sink更小更灵活。
  • signal/slot

C++ 标准中没能提供面向对象的函数指针. 面向对象的函数指针也被称为闭包(closures) 或委托(delegates), 在类似的语言中已经体现出了它的价值.

http://blog.csdn.net/jamesmf/article/details/7710122

http://www.chinaitlab.com/c/special/sjms/Index.html

http://www.cppblog.com/weiym/archive/2012/08/28/188515.html

http://blog.csdn.net/xie1xiao1jun/article/details/8262902

#include <iostream>
#include <vector>
#include <stdio.h>

using namespace std;

typedef void (*DownloadCallback)(const char* pURL, bool bOK);  
void DownloadFile(const char* pURL, DownloadCallback callback)  
{  
	cout << "\ncall back.\n" << endl;
    cout << "downloading: " << pURL << "" << endl;  
    callback(pURL, true);  
}  
void OnDownloadFinished(const char* pURL, bool bOK)  
{  
    cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;  
}

class SpiSink
{
public:  
    virtual void OnDownloadFinished(const char* pURL, bool bOK) = 0; 
};

class MySpi: public IDownloadSink  
{  
public:    
    virtual void OnDownloadFinished(const char* pURL, bool bOK)  
    {  
        cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;  
    }  
};  

class Api  
{  
public:  
    Api()  
    {
    	cout << "\nsink mode like ctp.\n" << endl;
    }  
  
    void DownloadFile(const char* pURL)  
    {  
        cout << "downloading: " << pURL << "" << endl;  
        if(m_pSink != NULL)  
        {  
            m_pSink->OnDownloadFinished(pURL, true);  
        }  
    }  
    void Registerspi(SpiSink* pSink)
    {
    	m_pSink = pSink;
    }
  
private:  
    SpiSink* m_pSink;  
};

/*
class CDownloadDelegateBase  
{  
public:  
    virtual void Fire(const char* pURL, bool bOK) = 0;  
};  
  
template<typename O, typename T>  
class CDownloadDelegate: public CDownloadDelegateBase  
{  
    typedef void (T::*Fun)(const char*, bool);  
public:  
    CDownloadDelegate(O* pObj = NULL, Fun pFun = NULL)  
        :m_pFun(pFun), m_pObj(pObj)  
    {  
    }  
     
    virtual void Fire(const char* pURL, bool bOK)  
    {  
        if(m_pFun != NULL  
            && m_pObj != NULL)  
        {  
            (m_pObj->*m_pFun)(pURL, bOK);  
        }  
    }  
  
private:  
    Fun m_pFun;  
    O* m_pObj;  
};  
  
template<typename O, typename T>  
CDownloadDelegate<O,T>* MakeDelegate(O* pObject, void (T::*pFun)(const char* pURL, bool))  
{  
    return new CDownloadDelegate<O, T>(pObject, pFun);  
}  
  
class CDownloadEvent  
{  
public:  
    ~CDownloadEvent()  
    {  
        vector<CDownloadDelegateBase*>::iterator itr = m_arDelegates.begin();  
        while (itr != m_arDelegates.end())  
        {  
            delete *itr;  
            ++itr;  
        }  
        m_arDelegates.clear();  
    }  
  
    void operator += (CDownloadDelegateBase* p)  
    {  
        m_arDelegates.push_back(p);  
    }  
  
    void operator -= (CDownloadDelegateBase* p)  
    {  
        ITR itr = remove(m_arDelegates.begin(), m_arDelegates.end(), p);  
  
        ITR itrTemp = itr;  
        while (itrTemp != m_arDelegates.end())  
        {  
            delete *itr;  
            ++itr;  
        }  
        m_arDelegates.erase(itr, m_arDelegates.end());  
    }  
  
    void operator()(const char* pURL, bool bOK)  
    {  
        ITR itrTemp = m_arDelegates.begin();  
        while (itrTemp != m_arDelegates.end())  
        {  
            (*itrTemp)->Fire(pURL, bOK);  
            ++itrTemp;  
        }  
    }  
  
private:  
    vector<CDownloadDelegateBase*> m_arDelegates;  
    typedef vector<CDownloadDelegateBase*>::iterator ITR;  
};  
  
  
class CMyDownloaderEx  
{  
public:  
    void DownloadFile(const char* pURL)  
    {  
        cout << "downloading: " << pURL << "" << endl;  
        downloadEvent(pURL, true);  
    }  
  
    CDownloadEvent downloadEvent;  
};  
  
class CMyFileEx  
{  
public:  
    void download()  
    {  
        CMyDownloaderEx downloader;  
        downloader.downloadEvent += MakeDelegate(this, &CMyFileEx::OnDownloadFinished);  
        downloader.DownloadFile("www.baidu.com");  
    }  
  
    virtual void OnDownloadFinished(const char* pURL, bool bOK)  
    {  
        cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;  
    }  
};  
*/

int main(int argc, char* argv[])  
{  
  
  	//callback
    DownloadFile("www.baidu.com", OnDownloadFinished);  
  
  	//sink
    CMyFile f1;  
    f1.download();  
  	
  	//类似ctp的回调方式 sink
  	Api* api = new Api();
  	MySpi* spi = new MySpi();
  	api->Registerspi((SpiSink*)spi);
  	api->DownloadFile("www.baidu.com");

  	/*Delegate
  	CMyFileEx ff;  
    ff.download();
    */

    return 0;  
}