作者:朱金灿

来源: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. Android实践 -- Android蓝牙设置连接

    使用Android Bluetooth APIs将设备通过蓝牙连接并通信,设置蓝牙,查找蓝牙设备,配对蓝牙设备 连接并传输数据,以下是Android系统提供的蓝牙相关的类和接口 BluetoothAd ...

  2. Project Euler 501 Eight Divisors (数论)

    题目链接: https://projecteuler.net/problem=501 题意: \(f(n)\) be the count of numbers not exceeding \(n\) ...

  3. angular6添加material-svgIcon

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

  4. js进阶 12-18 jquery如何实现自定义右键菜单(把问题分细)

    js进阶 12-18  jquery如何实现自定义右键菜单(把问题分细) 一.总结 一句话总结:用鼠标右键事件contextmenu,阻止系统默认事件,让做好的右键菜单显示出来,并且显示在我们出现的位 ...

  5. NVL与NVL2

      一.NVL函数是一个空值转换函数   NVL(表达式1,表达式2)   如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值. 该函数的目的是把一个空值(null)转换成一个实际的 ...

  6. [转载]Surging 分布式微服务框架使用入门

    前言 本文非 Surging 官方教程,只是自己学习的总结.如有哪里不对,还望指正. 我对 surging 的看法 我目前所在的公司采用架构就是类似与Surging的RPC框架,在.NET 4.0框架 ...

  7. python使用matplotlib画图

    python使用matplotlib画图 matplotlib库是python最著名的画图库.它提供了一整套和matlab类似的命令API.十分适合交互式地进行制图. 先介绍了怎样使用matplotl ...

  8. Java与模式:装饰(Decorator)模式

    装饰模式使用被装饰类的一个子类的实例.把client的调用委派到被装饰类,装饰模式的关键在于这样的扩展是全然透明的.   装饰模式在Java种使用也非常广泛,比方我们在又一次定义button.对话框等 ...

  9. 11、V4L2摄像头获取单幅图片测试程序

    #根据网上常见的一个测试程序修改而来 by rockie cheng#include <stdio.h>#include <stdlib.h>#include <stri ...

  10. 交换排序(java)

    package exchange_sort; import java.util.Random; /*各类交换排序  * ------数据存储范围1~s.length-1 ------  *主要包含   ...