金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
转自:用bind来解耦

应用了boost::bind, boost::function, boost::test
代码稍有修改。

#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/included/unit_test_framework.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <string>

using namespace std;

//声明一个函数指针的类型
typedef void (* ON_SEGMENT) (char *);

//用function<> 和指针回调指针来解除耦合
//注意解耦效果: CReader 和 CSaver 没有任何关系

class CReader
{
public:
    CReader()
    {
        m_pFunc=NULL;
        m_functor=NULL;
    };

    void UseFreeFunc(ON_SEGMENT pFunc)
    {
        m_pFunc=pFunc;
    };

    void UseFunctor(boost::function<void(char *)>  functor)
    {
        m_functor= functor;
    };

    void Read(char * pchar)
    {
        if(m_pFunc)
        {
            m_pFunc(pchar);
        };
        if(m_functor)
        {
            m_functor(pchar);
        };
    }

private:
    ON_SEGMENT m_pFunc;//函数指针
    boost::function<void(char *)>  m_functor; //函数对象
};

class CSaver
{
public:
    //接受输入的字符,保存在内部变量m_str
    void Input(char * pchar)
    {
        m_str.append(pchar);
    };

    string m_str;
};

BOOST_AUTO_TEST_CASE(test_bind)
{
    //两个类并不知道对方的任何细节
    CSaver  saver;
    CReader reader;

    //预先 把函数 CSaver::Input 和要操作的数据 &saver 注册到 reader
    //只要函数形式符合(返回值是void,传入参数是char *),都可以注册
    //解除CSaver 和 CReader的耦合
    //bind产生的函数对象,重载操作符()
    //函数对象的本质是 函数指针加this指针,即 操作和数据
    //函数对象 比 函数指针优越的地方是可以带有内部状态

    reader.UseFunctor( boost::bind(&CSaver::Input, &saver, _1) );

    //延时调用,解除CSaver 和 CReader的耦合
    //把字符从reader 放入 saver里面
    reader.Read("Hello");
    reader.Read("Mafeitao");

    BOOST_CHECK(saver.m_str=="HelloMafeitao");
}

//asio 里面的 async_accept 的简化版本
//可以接受 函数指针; 比如 async_accept(FreeFunc,Para)
//可以接受 函数对象; 比如
// CSaverFunctor func;
//async_accept(func,Para)
//可以接受 bind
template <typename AcceptHandler,typename Para>
void async_accept(AcceptHandler handler, Para p)
{
    handler(p);
};

// 自由函数,没有内部状态
void FreeFunc(char * pChar)
{
    printf("In FreeFunc %s\n", pChar);
}

BOOST_AUTO_TEST_CASE(bind_asio)
{
    //类 CSaver 和 模板函数 async_accept,没有任何关系
    CSaver saver;
    char *pchar="Hello";

    //bind生成一个临时的functor类 CSaverTemp
    //类似于
    /*
    class CSaverTemp
    {
    public:

        void operator ()(char * pchar)
        {
            m_str.append(pchar);
        };
        string m_str
    }

    CSaverTemp saver;
    async_accept(saver,pchar);
    }
    */
    //全局函数 async_accept,接受一个bind产生的函数对象( 函数指针和this指针)
    async_accept( boost::bind(&CSaver::Input, &saver,_1) , pchar);

    BOOST_CHECK(saver.m_str=="Hello");
    pchar="Mafeitao";
    async_accept( boost::bind(&CSaver::Input, &saver,_1) , pchar);
    BOOST_CHECK(saver.m_str=="HelloMafeitao");

    //接受 全局函数指针,和下面的效果一样
    async_accept( boost::bind(FreeFunc,_1), pchar);
    //接受 全局函数指针,和上面的效果一样
    async_accept( FreeFunc, pchar);
}

//带有模板函数的类
class TReader
{
public:
    //模板函数
    template <typename OnReadHandler,typename Para>
    void Read(OnReadHandler & handler, Para p)
    {
        //可以接受 函数指针,参数
        //可以接受 函数对象,参数
        //可以接受 bind
        handler(p);
    };
};

BOOST_AUTO_TEST_CASE(bind_template)
{
    TReader reader;
    CSaver saver;
    char *pchar="Hello";
    boost::function<void (char*)> handler
        = boost::bind(&CSaver::Input, &saver,_1);
    reader.Read(handler, pchar);
    BOOST_CHECK(saver.m_str=="Hello");

    pchar="Mafeitao";
    reader.Read(handler, pchar);
    BOOST_CHECK(saver.m_str=="HelloMafeitao");
}

//函数对象,重载操作符()
//函数对象的本质是 函数指针加this指针,即 操作和数据
//函数对象 比 函数指针优越的地方是可以带有内部状态
class CSaverFunctor
{
public:
    void operator ()(char * pchar)
    {
        m_str.append(pchar);
    };
    string m_str;
};

BOOST_AUTO_TEST_CASE(test_functor)
{
    //带有模板函数的类
    TReader reader;

    //函数对象
    CSaverFunctor saver;

    //把字符从reader 放入 saver里面
    char *pchar="Hello";
    reader.Read( saver , pchar);

    pchar="Mafeitao";
    reader.Read( saver , pchar);
    BOOST_CHECK(saver.m_str=="HelloMafeitao");
}

posted on 2008-09-12 16:52 金庆 阅读(924) 评论(0)  编辑 收藏 引用 所属分类: 1. C/C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理