`
yesjavame
  • 浏览: 693107 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

用bind来解耦

阅读更多
转自:用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");
}


分享到:
评论

相关推荐

    前端开源库-abind

    3. **解耦视图与模型**: `abind` 通过自动绑定,帮助开发者减少手动管理视图和模型之间绑定的繁琐工作,提高代码的可读性和可维护性。 4. **性能优化**: 除了基本的绑定功能,`abind` 可能还实现了优化,如延迟绑定...

    j2se中实现jndi的控制、管理

    在Java中,通常使用`Context`接口来代表命名上下文。通过`Context`,我们可以绑定(bind)、解绑(unbind)和查找(lookup)对象。 2. **目录服务**:目录服务除了提供命名功能外,还允许对对象进行基于属性的搜索...

    糯谷猪解耦联蛋白3和心脏型脂肪酸结合蛋白在骨骼肌中的表达和定位 (2011年)

    为了探索解耦联蛋白3 ( uncoupling protein3,UCP3)和心脏型脂肪酸结合蛋白 ( heart fatty acid-bind-ing protein,H-FABP)对骨骼肌细胞中脂肪代谢的调节作用,采用 RT-PCR和免疫组织化学方法,研究了地方猪 品种糯谷猪...

    JAVA火车售票系统

    4. **多线程**:火车票的售票操作可能会有多个用户同时进行,因此需要使用多线程技术来处理并发请求,确保数据的一致性和安全性。 5. **数据库连接**:为了持久化存储数据,系统需要与数据库进行交互。JAVA提供了...

    rabbitmq的常用使用

    在 Java 中,可以使用 RabbitMQ 的客户端库来收发消息。下面是一个简单的示例代码: 1. 生成者:创建一个生产者,用于发送消息到队列中。 2. 消费者:创建一个消费者,用于监听指定队列并消费消息。 3. 配置文件:...

    Guice与Spring框架的区别.pdf

    在这个方法中,我们使用了binder.bind方法将MyService接口绑定到MyServiceImpl实现类,并指定了Scopes.SINGLETON作用域,以确保MyServiceImpl对象是单例的。 Guice的其它使用特性 Guice还提供了一些其它的使用特性...

    Guice发音为juice,是Google为Java 11及以上版本提供的轻量级依赖注入框架.zip

    开发者可以创建自定义模块,通过`@Provides`注解的方法来提供实例,或者使用`bind()`方法将接口与其实现类绑定。模块可以被组合,以满足复杂应用的需求。 2. 绑定(Bindings):绑定是模块中定义的规则,它告诉...

    在MVC5中如何使用Ninject

    此外,Ninject还允许你使用拦截器来实现如日志记录、事务管理等跨切面关注点。 **6. 测试与解耦** 由于Ninject实现了依赖注入,你的代码变得更易于测试。你可以轻松地替换依赖于模拟对象进行单元测试,而无需担心...

    用JNDI绑定DataSource

    最后,调用`ctx.bind()`方法将数据源绑定到JNDI路径"mydata"下,这会在指定的文件系统路径下创建一个名为".bindings"的文件来存储绑定信息。 2. **读取数据源**: 在实际应用中,一旦数据源被绑定到JNDI,其他部分...

    ioc原理,简单实现BufferKnife

    使用`@Bind`注解在字段上,表示该字段将被注入。 ```java public class MyActivity extends AppCompatActivity { @Bind(R.id.text_view) TextView textView; } ``` 2. **生成的绑定代码**:注解处理器会生成一个...

    springinaction2-P2c5.pic

    章节可能涵盖了使用`@Autowired`进行依赖注入测试、`@Transactional`进行事务管理测试,以及模拟对象的使用。 6. **Spring Boot** 考虑到Spring框架的版本发展,第五章可能也会提及Spring Boot,这是一个简化...

    Guice可以匹敌Dagger的轻量级注入框架

    在这个模块中,我们可以使用`@Provides`注解的方法来指定如何创建或获取一个依赖。这些方法通常会利用其他已经注入的依赖来构建对象。例如: ```java public class MyModule extends AbstractModule { @Override ...

    android源码之用roboguice实现依赖注入.zip

    在这个模块中,你可以通过`bind()`方法指定类的实例或者使用`@Provides`注解的方法来提供依赖。 ```java public class AppModule extends RoboModule { @Override protected void configure() { bind...

    dojo-0.4.3-ajax.rar

    在0.4.3版本中,使用`dojo.require`来加载所需的模块。 3. **Dojo XHR(XMLHttpRequest)对象** AJAX的核心是异步数据交换,Dojo 提供了 `dojo.xhr` 对象来简化与服务器的通信。你可以使用`dojo.xhrGet`、`dojo....

    用Roboguice实现依赖注入

    依赖注入的核心思想是解耦组件之间的依赖关系,使得组件之间通过接口进行通信,而不是通过硬编码的方式来创建和管理彼此的实例。这使得代码更易于测试,因为我们可以轻松地替换依赖项以进行模拟或伪造。 Roboguice...

    使用socket和DTU通信.doc

    当前版本的Winsock已经实现了与具体协议的解耦,开发者可以利用它来调用各种协议的功能,其中TCP/IP协议最为常用。 - **核心作用**:Winsock 在计算机中提供了一个通信端口(即Socket),通过这个端口,计算机能够与...

    初试Guice(转)

    在模块中,你可以使用`bind()`方法来指定一个接口或抽象类与其实现类之间的绑定关系。 2. **注解(Annotation)**:Guice使用Java的注解来标记类或方法,表明它们需要依赖注入。例如,`@Inject`注解标识一个构造函数...

    Maven项目可用于其他项目简单快速实现SpringMVC

    Maven通过使用一个XML配置文件(pom.xml)来定义项目的构建过程和依赖关系,极大地简化了项目构建和维护工作。 SpringMVC则是Spring框架的一个模块,专门用于处理Web应用的模型-视图-控制器(MVC)架构。它提供了...

    DI(依赖注入) 实例下载

    依赖注入(Dependency Injection,简称DI)是一种设计模式,它在软件工程中被广泛应用于解耦组件之间的依赖关系,使得代码更加灵活、可测试和可维护。在这个实例中,我们将聚焦于Ninject,一个流行的.NET框架,用于...

    动态web应用程序开发框架AngularJS的特性分析.pdf

    AngularJS通过模板和ng-bind指令来实现双向数据绑定。当数据发生变化时,AngularJS会自动更新页面数据,反之亦然。 另外,AngularJS还具有依赖注入的特性。依赖注入是指在程序中将组件之间的依赖关系解耦的技术。...

Global site tag (gtag.js) - Google Analytics