作者:朱金灿

来源: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. 8.Swift教程翻译系列——控制流之条件

    3.条件语句 常常会须要依据不同的情况来运行不同的代码. 你可能想要在错误发生的时候运行一段额外的代码,或者当某个值变得太高或者太低的时候给他输出出来.要实现这些需求,你能够使用条件分支. Swift ...

  2. Windows 64位下 python3.4.3 安装numpy scipy

    Numpy: 1.在开始菜单搜索cmd打开 终端 2.在终端输入python -m pip install -U pip 3.到http://www.lfd.uci.edu/~gohlke/pytho ...

  3. windows 控制台下 无法获取完整的回车键值

    问题描述: 收集的网友分析: http://bbs.csdn.net/topics/370084904 因为C语言和UNIX的开发者是同事…… C语言里统一用的\n表示另起一行.微软的DOS受到了当时 ...

  4. Android OnGestureListener用法 识别用户手势 左右滑动

    Android可以识别用户的手势(即用户用手指滑动的方向),通过用户不同的手势,从而做出不同的处理 需要使用OnGestureListener 比如说看电子书的时候翻页,或者要滑动一些其他内容 直接上 ...

  5. 对inetd、xinetd与TCP_Wrapper的基本了解

    在Linux系统中有一个特殊的守护进程inetd(InterNET services Daemon),它用于Internet标准服务,通常在系统启动时启动.通过命令行可以给出inetd的配置文件,该配 ...

  6. [WASM] Create and Run a Native WebAssembly Function

    In this introduction, we show a simple WebAssembly function that returns the square root of a number ...

  7. lv resize

    # lvreduce -L -400G /dev/vg_atalinux001/lv_home # resize2fs   /dev/vg_atalinux001/lv_home resize2fs ...

  8. 每天一个JavaScript实例-操作元素定位元素

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  9. [Angular2 Form] patchValue, setValue and reset() for Form

    Learn how to update part of form model, full form model and reset whole form. We have form definetio ...

  10. 关于spyder的一些用法

    目前还不会用spyder,感觉不习惯,也没怎么用MATLAB 能记住几点算几点吧 1,双击程序左侧栏,加断点 1,按住Ctrl,点击函数,进入函数