作者:朱金灿

来源: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. Python编写Appium测试用例(2)

    #coding=utf-8import os,sysimport unittestfrom appium import webdriverimport timefrom selenium.webdri ...

  2. zeromq and jzmq

    install c test install jzmq java test Storm UI Cluster Summary Version Nimbus uptime Supervisors Use ...

  3. Could not find action or result: There is no Action mapped for namespace [/] and action name [GetG

    Could not find action or result: /car/GetGpsDataAction  There is no Action mapped for namespace [/] ...

  4. 逻辑与和逻辑或:&& 、||

    逻辑或:首先看左边是真还是假(除了那5个都是真),如果为真,返回左边值,如果为假,返回右边的值 逻辑与:和逻辑或相同,先看左边的值是真是假,如果左边为真返回右边的值,左边为假返回左边的值 在两者同时出 ...

  5. 打开utf-8文件乱码的解决方法

    gvim一直用的好好的,但是今天看一网友贴出来的代码时,却发现中文显示乱码了.... 使用notepad++打开,右下角显示是utf-8 w/0 BOM. 马上放狗, 发现解决方法如下:   在_vi ...

  6. vue中的select框的值动态绑定

    <--这两种写法效果一样--> 1: <select v-model="wxStatus"> <option label="已添加" ...

  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. 可视化格式模型(visual formatting model)

    原文 简书原文:https://www.jianshu.com/p/7632f16ff555 大纲 1.认识可视化模型 2.可视化模型的内容 3.可视化模型的影响因素 1.认识可视化模型 盒子模型是C ...

  9. 【a903】石子归并

    Time Limit: 10 second Memory Limit: 2 MB 问题描述 在一个圆形操场的四周摆放着N堆石子(N<= 100),现要将石子有次序地合并成一堆.规定每次只能选取相 ...

  10. ERROR:column &quot;rolcatupdate&quot; does not exist

    1.错误描写叙述 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/ ...