使用 C++ template 进行多厂商接口的适配
题目: 设计一个虚拟聊天机器人
好吧,我非常想要一个能和我聊天的机器人,于是我设计一个机器人 class RobotTalker,它可能是从某个 Robot 类继承而来,但,先不管那么多。我只是希望这个机器人能同我正常聊天,以排除宅男的孤独,给我一种存在感。
默认语言接口
我对虚拟机器人有一个特殊的需求,就是要求它能说多种语言,有时可以用普通话和我聊天,有时也能用家乡话给父母解解闷,有时可以在网络上跟国外的程序员们交流一下技术,权当是个翻译。但我只会中文,我自己只能研发出它的中文语言模块。
我给 RobotTalker 提供的随机附带默认的语言接口是 DefaultCompany.h:
在我发布了我要做聊天机器人的信息后,收到两个网友的来信,有意为我提供英语模块和俄语模块,他们的接口采取了和我默认接口同样的形式。
英语接口 CompanyEngland.h
俄语接口 CompanyRussia.h
同样,他们的具体实现都是以动态库形式提供的。
不同的产品版本?
不过,这两个网友给我提了一个交换条件,就是我的机器人做好之后,他们也要一份拷贝,而且他们只想要自己的语言版本。这下可难住我了,看来我得想办法针对我们三个人不同的需求来适配接口。首先,为我们三个人的语言模块分别分配一个厂商代码,根据 CompanyCode 来决定 Robot 的实现版本。
宏
我先使用传统的 C 语言形式设计了如下的 RobotTalker。
依赖于宏编译出不同版本的这种实现形式,不管看起来怎么别扭,但至少已经实现了我们三个人的需求。不过我不敢把这种代码发布给我的客户,在一个宏起作用的情况下,另外两个语言接口是不会被编译的,而且我每次发布代码都要更换宏定义,编译三次啊。
模板
有没有能一劳永逸的方法呢?C++的模板是代替这种宏编译的一种不错的形式。我给机器人设计一个指定类型作为模板参数的模板函数,我的中文模块接口作为模板的一般形式,而英语和俄语作为模板的特化版本,这样客户代码调用机器人代码时,只需要把 CompanyCode 作为模板参数传递给 RobotTalker 就可以了。
首先看机器人的语言接口如何实现:
我的机器人代码只需要一套,所有的接口时时刻刻都处于编译器的检查范围,也就是说,所有的厂商接口都会始终被编译。而且,只使用英语模块的客户,另外两个接口根本不会编译为可执行代码,不会占用多余的内存空间,和宏一样的效果。
客户要使用这个 RobotTalker 实现自己定义语言的机器人时,那就很方便了。
总结
本文只针对多厂商接口(而且接口格式相同)这个需求展开了讨论,其中的 SpeakLanguage 无实际意义, 只是用来做模板的示范, 目的是推介一下 C++ Template 的威力,至于要实现不同功能的机器人之类的话题,那是设计模式的范畴,就不多嘴了。
另外针对上述需求,还有一种实现方式,就是根据厂商代码使用不同厂商的接口函数,初始化一个函数指针,客户代码调用时设定自己的厂商代码,调用的函数指针自然就是自己的接口函数。但我总觉得函数模板的形式更优雅一些。
版权声明: 本文为 InfoQ 作者【老王同学】的原创文章。
原文链接:【http://xie.infoq.cn/article/58afd970ac9e323b436f8e3ac】。文章转载请联系作者。
评论