前段时间在用c++设计一个项目的框架时遇见了一些问题,内部模块间的接口过于庞大,因此需要一种统一的方式来实现参数传递,后来就想到了C++的模板,并且做了一个雏形。虽然项目还没开始就挂了,但是我却继续研究了下去,于是就出现了几个泛型类,个人感觉可以在很多的项目设计中通用。
这里介绍了一种模块间传递参数及实现回调机制的泛型接口,并实现了一个泛化的回调管理器。本文的内容对于修补代码和解BUG等类型的工作而言没有任何意义,但如果你要从零开始设计一个软件或者重构一个系统的话相信你可以从文中获得一点好处。理解本文的内容需要一定的C++模板相关知识。由于能力限制,这里讲的内容难免会有错误,欢迎指正和提供更简洁的实现方案。
关键字:模板、参数传递、回调函数
参考资料:《C++设计新思维:范型编程与设计模式之应用》
1 模块的参数传递
1.1 适用范围
当我们设计一个软件时,有时会需要在两个模块或者类之间传递类型不同数量不同的N组参数,为了实现这个目的不得不设计N个接口,如果这两个互相通信的类是抽象接口的话,当你需要修改或添加参数及方法时会十分麻烦,因为还需要同时修改所有的子类。更重要的是一个全功能接口的类违反了设计的美学。
当然你可以利用定义多个结构体,并强制转化为void*然后附加一个消息类型的方案避免上述问题,但是这种方法会导致产生多个结构体,并且转化总是会成功,即使是在你写错的情况下。
这里介绍的方法也是需要一个附加的消息类型,但是没有使用void*带来的各种麻烦。
1.2 使用方法
这里介绍一些这个方案的例子代码。
//模块1中代码:
CParam *p1 = CreateParam(2.0,“12345”,false,33);
CParam *p2 = CreateParam(5);
//模块2中代码:
double d;
const char *s;
bool b;
int i;
GetParam(p1,d,s,b,i);//如果转化失败会导致一个断言或抛出异常
GetParam(p2,di);
这里你只需要调用CreateParam接口传递任意数目和类型的参数并生成一个CParam *变量,然后通过某个特定的消息传递给其他模块。通过这个方法你可以少定义很多无聊的结构体,并且转化失败时会得到通知。
1.3 实现
首先来定义转化函数:
template<class R,class T>
R param_cast(T t)
{
R r = dynamic_cast<R>(t);
assert(r && t);
if (!r)
{
throw param_bad_cast();
}
return r;
}
为了得到会失败的转化,我们需要使用dynamic_cast