作者:朱金灿

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

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

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

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

  1. // BaseAlgo.h
  2. #include <string>
  3. #include <boost/any.hpp>
  4.  
  5. class CBaseAlgo
  6. {
  7. public:
  8.  
  9. CBaseAlgo(std::string& strID);
  10.  
  11. virtual ~CBaseAlgo(void);
  12.  
  13. virtual bool run(boost::any& anyData);
  14.  
  15. protected:
  16.  
  17. std::string m_strID;
  18.  
  19. };
  20.  
  21. // BaseAlgo.cpp
  22. CBaseAlgo::CBaseAlgo(std::string& strID)
  23. {
  24. m_strID = strID;
  25. }
  26.  
  27. CBaseAlgo::~CBaseAlgo(void)
  28. {
  29. }
  30.  
  31. bool CBaseAlgo::run( boost::any& anyData )
  32. {
  33. return false;
  34. }

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

  1. // AlgoDemo1.h
  2.  
  3. #include "BaseAlgo.h"
  4. #include "AlgoParameter.h"
  5.  
  6. class CAlgoDemo1: public CBaseAlgo
  7. {
  8. public:
  9. CAlgoDemo1(std::string& strID);
  10.  
  11. virtual ~CAlgoDemo1(void);
  12.  
  13. bool run(boost::any& anyData);
  14. };
  15.  
  16. // AlgoDemo1.cpp
  17. #include "AlgoDemo1.h"
  18.  
  19. CAlgoDemo1::CAlgoDemo1(std::string& strID):CBaseAlgo(strID)
  20. {
  21. }
  22.  
  23. CAlgoDemo1::~CAlgoDemo1(void)
  24. {
  25. }
  26.  
  27. bool CAlgoDemo1::run( boost::any& anyData )
  28. {
  29. if(anyData.type() == typeid(stAlgoParameter1))
  30. {
  31. stAlgoParameter1 ret = boost::any_cast<stAlgoParameter1>(anyData);
  32. ret.m_nNo = 100;
  33. ret.m_strName = "John";
  34. // 如果需要返回值,那就需要重新对anyData进行赋值
  35. anyData = ret;
  36. }
  37. return true;
  38. }

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

  1. // AlgoParameter.h
  2.  
  3. struct stAlgoParameter1
  4. {
  5. std::string m_strName;
  6. int m_nNo;
  7. };

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

  1. // main.cpp
  2.  
  3. #include <boost/any.hpp>
  4. #include "BaseAlgo.h"
  5. #include "AlgoParameter.h"
  6.  
  7. // 根据算法ID找到算法类,具体是返回创建的算法类的指针
  8. CBaseAlgo* GetAlgoObj(std::string& strAlgoID)
  9. {
  10. // 这里动态加载算法模块,算法模块都导出一个接口来创建算法对象,具体不予实现
  11. }
  12.  
  13. int _tmain(int argc, _TCHAR* argv[])
  14. {
  15. stAlgoParameter1 info;
  16. boost::any anyData = info;
  17. info = boost::any_cast<stAlgoParameter1>(anyData);
  18. // 调用动态规划算法
  19. std::string strAlgoID = "DynamicProgramming";
  20. CBaseAlgo* pAlgoObj = GetAlgoObj(strAlgoID);
  21. if(NULL!=pAlgoObj)
  22. pAlgoObj->run(anyData);
  23.  
  24. getchar();
  25. return 0;
  26. }

这样设计的好处是算法模块和调用算法的模块只需要包含定义参数结构体的头文件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. 洛谷 P2368 EXCEEDED WARNING B

    P2368 EXCEEDED WARNING B 题目背景 SGU 107 题目描述 求有多少个平方后末尾为987654321的n位数 输入输出格式 输入格式: 整数n 输出格式: 答案,即[b]“平 ...

  2. iOS ERROR: unable to get the receiver data from the DB 解决方式

    这个错误通常发生在iOS7其中,可能是缓存的导致的问题. 解决步骤: 右击Finder,选择 Go to Folder 复制上:"~/Library/Application Support/ ...

  3. 【原创】面向对象版本地CPU资源占用监控脚本

    前期准备: 1.python2.7环境 2.相关第三方库下载安装 脚本工作过程: 1.根据输入的进程名判断进程是否存在,如果不存在则进行等待,直到检测到进程PID,中途进程退出抛出异常,键入enter ...

  4. Ten ways to improve the performance of large tables in MySQL--转载

    原文地址:http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-mysql.html Today I ...

  5. What is corresponding Cron expression to fire in every X seconds, where X > 60? --转载

    原文地址:http://stackoverflow.com/questions/2996280/what-is-corresponding-cron-expression-to-fire-in-eve ...

  6. javascript的组成

    ECMAScript:(3/5/6/7) 它是JS语言的标准,规定了JS的编程语法和基础核心知识. DOM:document object model 文档对象模型,提供给JS很多的操作页面中元素的属 ...

  7. postman--基本使用1

    本文转自:http://blog.csdn.net/five3/article/details/53021084 HTTP的接口测试工具有很多,可以进行http请求的方式也有很多,但是可以直接拿来就用 ...

  8. 基于bootstrap的主流框架有哪些

    基于bootstrap的主流框架有哪些 一.总结 一句话总结:其实可以直接百度bootstrap后台模板,出来一大堆,想用哪个用哪个. 二.[前端框架系列]浅谈当前基于bootstrap框架的几种主流 ...

  9. 【习题5-5 UVA-10391】Compound Words

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举每一个串的分割点. 看看左右两个串在不在字符串中即可. [代码] #include <bits/stdc++.h> ...

  10. ORA-00119: invalid specification for system parameter LOCAL_LISTENER;

    错误提示内容及上下文环境: SQL> grant sysdba to weng;grant sysdba to weng*第 1 行出现错误:ORA-01034: ORACLE not avai ...