作者:朱金灿

来源:http://blog.csdn.net/clever101

在开发大型系统中,遵循这样一个原则:模块之间低耦合,模块内高内聚。比如系统中模块有界面模块和算法模块两种,一般是界面模块调用算法模块,这样的话界面模块依赖于算法模块。现在我要实现这样界面和算法分离,即界面模块不依赖于算法模块。除了界面模块不依赖于算法模块,我要应对的另一个挑战是算法参数是不确定的,就是说要容纳任意的参数类型。

为此我找到了boost::any。boost::any的好处是它能容纳任意类型的数据。它可以很方便的进行模块间函数之间不确定参数传递。具体做法是这样的:

1. 在系统底层定义一个算法基类CBaseAlgo,其接口如下:

// BaseAlgo.h
#include <string>
#include <boost/any.hpp> class CBaseAlgo
{
public: CBaseAlgo(std::string& strID); virtual ~CBaseAlgo(void); virtual bool run(boost::any& anyData); protected: std::string m_strID; }; // BaseAlgo.cpp
CBaseAlgo::CBaseAlgo(std::string& strID)
{
m_strID = strID;
} CBaseAlgo::~CBaseAlgo(void)
{
} bool CBaseAlgo::run( boost::any& anyData )
{
return false;
}

2.所有的算法模块都有一个算法类,算法类都派生自CBaseAlgo,示例如下:

// AlgoDemo1.h

#include "BaseAlgo.h"
#include "AlgoParameter.h" class CAlgoDemo1: public CBaseAlgo
{
public:
CAlgoDemo1(std::string& strID); virtual ~CAlgoDemo1(void); bool run(boost::any& anyData);
}; // AlgoDemo1.cpp
#include "AlgoDemo1.h" CAlgoDemo1::CAlgoDemo1(std::string& strID):CBaseAlgo(strID)
{
} CAlgoDemo1::~CAlgoDemo1(void)
{
} bool CAlgoDemo1::run( boost::any& anyData )
{
if(anyData.type() == typeid(stAlgoParameter1))
{
stAlgoParameter1 ret = boost::any_cast<stAlgoParameter1>(anyData);
ret.m_nNo = 100;
ret.m_strName = "John";
// 如果需要返回值,那就需要重新对anyData进行赋值
anyData = ret;
}
return true;
}

其中AlgoParameter.h定义了算法参数结构,代码如下:

// AlgoParameter.h

struct stAlgoParameter1
{
std::string m_strName;
int m_nNo;
};

3. 然后在调用算法模块的地方,这里假定为main函数,这样调用:

// main.cpp

#include <boost/any.hpp>
#include "BaseAlgo.h"
#include "AlgoParameter.h" // 根据算法ID找到算法类,具体是返回创建的算法类的指针
CBaseAlgo* GetAlgoObj(std::string& strAlgoID)
{
// 这里动态加载算法模块,算法模块都导出一个接口来创建算法对象,具体不予实现
} int _tmain(int argc, _TCHAR* argv[])
{
stAlgoParameter1 info;
boost::any anyData = info;
info = boost::any_cast<stAlgoParameter1>(anyData);
// 调用动态规划算法
std::string strAlgoID = "DynamicProgramming";
CBaseAlgo* pAlgoObj = GetAlgoObj(strAlgoID);
if(NULL!=pAlgoObj)
pAlgoObj->run(anyData); getchar();
return 0;
}

这样设计的好处是算法模块和调用算法的模块只需要包含定义参数结构体的头文件AlgoParameter.h,调用算法的模块并不依赖于算法模块。同时boost::any的特性保证了可以传递任意类型参数。

参考文献:

1.boost源码剖析之:泛型指针类any之海纳百川

2.一种松耦合的分层插件系统的设计和实现

boost::any在降低模块之间耦合性的应用的更多相关文章

  1. C++程序的耦合性设计

    声明:本文部分采用和参考<代码里的世界观-通往架构师之路>中内容,可以说是该书中耦合性一章的读后感,感谢该书的作者余叶老师的无私分享. 1.什么是耦合? 耦合其实就是程序之间的相关性. 程 ...

  2. 08 Spring框架的概念、优势、体系结构、耦合性和IOC(反转控制)

    1.spring介绍 Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect ...

  3. ng-repeat循环出来的部分调用同一个函数并且实现每个模块之间不能相互干扰

    使用场景:用ng-repeat几个部分,每个部分调用同一个函数,但是每个模块之间的功能不能相互干扰 问题:在用repeat实现.content块repeat的时候打算这样做:新建一个空的数组(nmbe ...

  4. 如何使用 require.js ,实现js文件的异步加载,避免网页失去响应,管理模块之间的依赖性,便于代码的编写和维护。

    一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代 ...

  5. 多线程(四) 实现线程范围内模块之间共享数据及线程间数据独立(Map集合)

    多个线程访问共享对象和数据的方式 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 2.如果每个线程执行的代码 ...

  6. 多线程(三) 实现线程范围内模块之间共享数据及线程间数据独立(ThreadLocal)

    ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.JDK 1.2的版本中就提供java.lang.ThreadLocal,使用这个工具类可以很简洁地编写出优美的多线程程序,Threa ...

  7. nodejs选择JavaScript作为开发语言,是因为一般的开发语言的标准库都是带有IO模块的,并且通常这个 模块是阻塞性的,所以nodejs选择了没有自带IO模块的Javascript

    Javascrip本身不带IO功能,nodejs选择JavaScript作为开发语言,是因为一般的开发语言的标准库都是带有IO模块的,并且通常这个 模块是阻塞性的,所以nodejs选择了没有自带IO模 ...

  8. 关于gcc、glibc和binutils模块之间的关系,以及在现有系统上如何升级的总结

    http://blog.csai.cn/user1/265/archives/2005/2465.html 一.关于gcc.glibc和binutils模块之间的关系 1.gcc(gnu collec ...

  9. 【转】关于gcc、glibc和binutils模块之间的关系

    原文网址:http://www.mike.org.cn/articles/linux-about-gcc-glibc-and-binutils-the-relationship-between-mod ...

随机推荐

  1. 泛型T和Object 区别?

    T表示不能确定具体类型,Object是超类.最直接的区别在于:当用T时,开发人员不用强转类型 如:public T MethodName(T t); 如果传入String,则T就是String,所以返 ...

  2. 【BZOJ 1146】【CTSC 2008】网络管理network

    一句话题意,树链上带改动区间第k大 感觉能够dfs+主席树O(nlog2n)过掉,但我不会写= = 于是写的线段树套平衡树+链剖+二分(改动O(nlog3n),查询O(nlog4n)慢了好多啊QAQ) ...

  3. SSH进阶(2)——用Struts拦截器实现登陆限制

    拦截器从字面意思来看就是限制.限制用户訪问某些网页.在Action提出请求之前用拦截器来做权限设置,让符合的用户跳入对应的界面中.近期做的一个商城项目中就用到了自己定义的拦截器,实现了一个简单的ses ...

  4. 鲁德http://www.testroad.org/topic/76

     [最新的招聘信息]:1.联动优势科技有限公司招聘性能测试工程师       薪资20K左右 http://ask.testroad.org/article/4042.上海-交通银行总行-性能测试专家 ...

  5. windows版 nginx配置反向代理实例教程 跳转tomcat和php网站

    抄自 https://www.cnblogs.com/j-star/p/8785334.html 个人理解 nginx端口设置为80,简称n tomcat端口设置为其他,例如8080,简称t php网 ...

  6. 每日技术总结:setInterval,setTimeout,文本溢出,小程序,wepy

    前言: 项目背景:vue,电商,商品详情页 1.倒计时,倒计到0秒时停止 data () { return { n: 10 } }, created () { let int = setInterva ...

  7. [AngularFire 2] Joins in Firebase

    Lets see how to query Firebase. First thing, when we do query, 'index' will always help, for both SQ ...

  8. IOS日期转为今天昨天形式

    近期项目有类似QQ空间展示动态的UI,模仿了QQ空间的时间显示.在此记录,以备查阅. 这是QQ空间的ui: 时间显示为: 1.今天-->今天 xx:xx(今天 15:39) 2.昨天--> ...

  9. wikioi 1051哈希表

    题目描写叙述 Description 给出了N个单词,已经按长度排好了序.假设某单词i是某单词j的前缀,i->j算一次接龙(两个同样的单词不能算接龙). 你的任务是:对于输入的单词,找出最长的龙 ...

  10. View的事件分发机制解析

    引言 Android事件构成 在Android中,事件主要包含点按.长按.拖拽.滑动等,点按又包含单击和双击,另外还包含单指操作和多指操作.全部这些都构成了Android中的事件响应.总的来说.全部的 ...