作者:朱金灿

来源: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. Jpa 的Persistence.xml配置讲解

    <?xml version="1.0"?> <persistence xmlns="http://java.sun.com/xml/ns/persist ...

  2. amazeui学习笔记--css(常用组件10)--导航条Topbar

    amazeui学习笔记--css(常用组件10)--导航条Topbar 一.总结 1. 导航条:就是页面最顶端的导航条:在容器上添加 .am-topbar class,然后按照示例组织所需内容.< ...

  3. 深度学习利器: TensorFlow系统架构及高性能程序设计

    2015年11月9日谷歌开源了人工智能平台TensorFlow,同时成为2015年最受关注的开源项目之一.经历了从v0.1到v0.12的12个版本迭代后,谷歌于2017年2月15日发布了TensorF ...

  4. RMAN-03002、RMAN-06059

    使用RMAN备份的时候无法正常备份,抛出以下错误: RMAN-03002: failure of backup command at 04/20/2015 18:55:45 RMAN-06059: e ...

  5. 编程——C语言的问题,堆栈

    堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...

  6. angular6添加material-svgIcon

    1. app/assets/util/util.svg.ts 统一管理svg字体库,避免各个模块分散加载.所以使用公共文件统一处理 再到core.module.ts中引入.在core模块下的所有组价都 ...

  7. SpringBoot 使用yml配置 mybatis+pagehelper+druid+freemarker实例

    SpringBoot 使用yml配置 mybatis+pagehelper+druid+freemarker实例 这是一个简单的SpringBoot整合实例 这里是项目的结构目录 首先是pom.xml ...

  8. [React] Style the body element with styled-components and "injectGlobal"

    In this lesson, we see how we can apply styles globally with the "injectGlobal" helper met ...

  9. App.js和App.css(用于移动应用的js和css)

    App.js和App.css(用于移动应用的js和css) 一.App.js和App.css(用于移动应用的js和css) App.js 是一个轻量级的 JavaScript UI 库,用来创建移动的 ...

  10. (转载)iis7下站点日志默认位置

    转自http://www.cnblogs.com/mincyw/p/3425468.html iis7下站点日志默认位置   在iis6时,通过iis管理器的日志配置可以找到站点日志存储的位置. 但是 ...