写点什么

使用 C++ template 进行多厂商接口的适配

作者:老王同学
  • 2023-03-13
    广东
  • 本文字数:1832 字

    阅读完需:约 6 分钟

题目: 设计一个虚拟聊天机器人


好吧,我非常想要一个能和我聊天的机器人,于是我设计一个机器人 class RobotTalker,它可能是从某个 Robot 类继承而来,但,先不管那么多。我只是希望这个机器人能同我正常聊天,以排除宅男的孤独,给我一种存在感。


默认语言接口

我对虚拟机器人有一个特殊的需求,就是要求它能说多种语言,有时可以用普通话和我聊天,有时也能用家乡话给父母解解闷,有时可以在网络上跟国外的程序员们交流一下技术,权当是个翻译。但我只会中文,我自己只能研发出它的中文语言模块。

我给 RobotTalker 提供的随机附带默认的语言接口是 DefaultCompany.h:

#ifndef Default_Interface_h#define Default_Interface_h void SpeakInChinese(); //函数的具体实现可能在另外一个.cpp文件中,也有可能在一个单独的dll中 #endif
复制代码

在我发布了我要做聊天机器人的信息后,收到两个网友的来信,有意为我提供英语模块和俄语模块,他们的接口采取了和我默认接口同样的形式。

英语接口 CompanyEngland.h

#ifndef Company_England_h#define Company_England_h void SpeakInEnglishUK(); #endif
复制代码

俄语接口 CompanyRussia.h

#ifndef Company_Russia_h#define Company_Russia_h void SpeakInRussian(); #endif
复制代码

同样,他们的具体实现都是以动态库形式提供的。

不同的产品版本?

不过,这两个网友给我提了一个交换条件,就是我的机器人做好之后,他们也要一份拷贝,而且他们只想要自己的语言版本。这下可难住我了,看来我得想办法针对我们三个人不同的需求来适配接口。首先,为我们三个人的语言模块分别分配一个厂商代码,根据 CompanyCode 来决定 Robot 的实现版本。


我先使用传统的 C 语言形式设计了如下的 RobotTalker。

class RobotTalker{public:    RobotTalker(){};    virtual ~RobotTalker(){};     void SpeakLanguage();}; //函数实现:根据宏定义,编译不同的接口。void RobotTalker::SpeakLanguage(){#ifdef DefaultCompanyCode    SpeakInChinese();#endif #ifdef CompanyRussiaCode    SpeakInRussian();#endif #ifdef ComanyEnglandCode    SpeakInEnglishUK();#endif}
复制代码

依赖于宏编译出不同版本的这种实现形式,不管看起来怎么别扭,但至少已经实现了我们三个人的需求。不过我不敢把这种代码发布给我的客户,在一个宏起作用的情况下,另外两个语言接口是不会被编译的,而且我每次发布代码都要更换宏定义,编译三次啊。

模板

有没有能一劳永逸的方法呢?C++的模板是代替这种宏编译的一种不错的形式。我给机器人设计一个指定类型作为模板参数的模板函数,我的中文模块接口作为模板的一般形式,而英语和俄语作为模板的特化版本,这样客户代码调用机器人代码时,只需要把 CompanyCode 作为模板参数传递给 RobotTalker 就可以了。


首先看机器人的语言接口如何实现:


#ifndef Robot_Reader_h#define Robot_Reader_h
#include "DefaultCompany.h"#include "CompanyEngland.h"#include "CompanyRussia.h"
//厂商代码const int DefaultCompanyCode = 1;const int CompanyEnglandCode = 100;const int CompanyRussiaCode = 200;
//聊天机器人class RobotTalker{public: RobotTalker(){}; virtual ~RobotTalker(){}; template<int CompanyCode> void SpeakLanguage();};
复制代码

我的机器人代码只需要一套,所有的接口时时刻刻都处于编译器的检查范围,也就是说,所有的厂商接口都会始终被编译。而且,只使用英语模块的客户,另外两个接口根本不会编译为可执行代码,不会占用多余的内存空间,和宏一样的效果。

客户要使用这个 RobotTalker 实现自己定义语言的机器人时,那就很方便了。


#include "RobotTalker.h" int main(){    RobotTalker robot;    robot.SpeakLanguage<CompanyEnglandCode>(); //讲英语    robot.SpeakLanguage<DefaultCompanyCode>(); //讲中文     RobotTalker tRobotRussian;    robot.SpeakLanguage<CompanyRussiaCode>(); //讲俄语}
复制代码

总结

本文只针对多厂商接口(而且接口格式相同)这个需求展开了讨论,其中的 SpeakLanguage 无实际意义, 只是用来做模板的示范, 目的是推介一下 C++ Template 的威力,至于要实现不同功能的机器人之类的话题,那是设计模式的范畴,就不多嘴了。

另外针对上述需求,还有一种实现方式,就是根据厂商代码使用不同厂商的接口函数,初始化一个函数指针,客户代码调用时设定自己的厂商代码,调用的函数指针自然就是自己的接口函数。但我总觉得函数模板的形式更优雅一些。


发布于: 2023-03-13阅读数: 21
用户头像

老王同学

关注

还未添加个人签名 2020-04-30 加入

还未添加个人简介

评论

发布
暂无评论
使用C++ template进行多厂商接口的适配_c++_老王同学_InfoQ写作社区