C++插件机制的一种实现方法(对象工厂)
发布日期:2021-10-03 22:59:40 浏览次数:27 分类:技术文章

本文共 3230 字,大约阅读时间需要 10 分钟。

背景

在我们的实际开发过程中,经常会开发一些插件,比较常见的例子如:给你 DataHandler,它是一个抽象类,提供一些数据操作的接口,然后插件开发者就需要继承DataHandler,并按需求实现对应的接口,将其作为插件,编译到最终的二进制程序中,最后通过配置文件指定生效该插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//  data_handler.h
 
Class DataHandler {
 
public
:
 
virtual
bool
Handle(std::vector<Data*> data_list) =0;
 
virtual
~DataHandler(){}
 
};
 
REGISTER_REGISTER(DataHandler)
 
#define REGISTER_DATA_HANDLER(name) REGISTER_CLASS(DataHandler, name)
1
2
3
4
5
6
7
8
9
// my_data_handler.h
 
class
MyDataHandler :
public
DataHandler {
 
public
:
 
virtual
bool
Handle(std::vector<Data*> result_list);
 
};
1
2
3
4
5
6
7
8
// my_data_handler.cc
 
bool
MyDataHandler::Handle(std::vector<Data*> data_list) {
 
// Implemention...
 
}
REGISTER_DATA_HANDLER(MyDataHandler)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// configure file
 
DataHandler{
 
name : MyDataHanlder,
 
prior   : 1
 
}
 
DataHanlder{
 
name : YourDataHandler,
 
prior   : 1
 
}

此时你只需把你的MyDataHandler编译为动态库或者是静态库,并链接到最终二进制中,在数据处理时就会调用你的DataHandler。是不是很方便开发哈,这就是所谓的插件开发思想。下面主要介绍下具体的实现。

实现思想

想要实现上述功能的插件框架,主要从以下几个方面着手解决:

1. 如何组织不同类型的插件,如目前有DataHanlder,但是系统可能也支持ServiceHanlder等等;某类插件可能包含多个具体的实例的插 件,那又如何组织;这里很容易就想到了双层map的数据结构,如下图所示,每层Map的Key都插件类型或者具体插件名字,value为对应的工厂对象, 工厂对象生成对应的实例,具体如下图所示:

2.  如何生成对象工厂类呢? 这里首先不能将这个工作交给插件开发者,一方面开发量增大,另一方面也暴漏系统实现细节;但是也不能框架开发者手工实现,因为框架本身无法预知都有哪些插件需要开发。

所以可能的方法包括模板函数或者是宏定义了,本文使用宏定义进行实现,包括插件类型工厂和某个插件工厂。

源代码

注解:__attribute__(construtor) void register_factory_##clazz##name(); 实现在main()函数调用前进行调用

在主干程序中通过以下的方式调用插件DataHandler:

1
2
3
DataHandler data_handler = DataHandlerRegister::GetInstanceByName(
"MyDataHandler"
);
 
data_handler->Handle(data_list);

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <map>
#include <string>
 
class
ObjectFactory {
 
public
:
 
ObjectFactory() {}
 
virtual
~ObjectFactory() {}
 
virtual
Any NewInstance() {
 
return
Any();
 
}
 
private
:
 
DISALLOW_COPY_AND_ASSIGN(ObjectFactory);
};
typedef
std::map<std::string, ObjectFactory*> FactoryMap;
typedef
std::map<std::string, FactoryMap> BaseClassMap;
BaseClassMap& global_factory_map(); 
// 在.cc文件中实现,保存静态变量factory_map
 
#define REGISTER_REGISTERER(base_class) \
 
class
base_class ## Registerer { \
 
typedef
::registerer::FactoryMap FactoryMap; \
 
public
: \
 
static
base_class *GetInstanceByName(
const
::std::string &name) { \
 
FactoryMap &map = ::registerer::global_factory_map()[#base_class]; \
 
FactoryMap::iterator iter = map.find(name); \
 
if
(iter == map.end()) { \
 
LOG(ERROR) <<
"Get instance "
<< name <<
" failed."
; \
 
return
NULL; \
 
} \
 
return
iter->second->NewInstance(); \
 
} \
 
static
bool
IsValid(
const
::std::string &name) { \
 
FactoryMap &map = ::registerer::global_factory_map()[#base_class]; \
 
return
map.find(name) != map.end(); \
 
} \
 
}; \
 
#define REGISTER_CLASS(clazz, name) \
 
namespace
registerer { \
 
class
ObjectFactory##clazz##name :
public
::registerer::ObjectFactory { \
 
public
: \
 
clazz* NewInstance() { \
 
return
new
name(); \
 
} \
 
}; \
 
void
register_factory_##clazz##name() { \
 
::registerer::FactoryMap &map = \
 
::registerer::global_factory_map()[#clazz]; \
 
if
(map.find(#name) == map.end()) \
 
map[#name] =
new
ObjectFactory##clazz##name(); \
 
} \
 
__attribute__((constructor))
void
register_factory_##clazz##name(); \
 
}
来自
  本文链接:
 

转载地址:https://blog.csdn.net/lclflash/article/details/8856850 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:插件式设计的架构模型与实例
下一篇:用C++实现插件体系结构

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月19日 15时01分34秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

AndroidStudio_android实现双击_3击_监听实现---Android原生开发工作笔记240 2019-04-26
C++_类和对象_对象特性_初始化列表---C++语言工作笔记045 2019-04-26
AndroidStudio安卓原生开发_UI高级_DrawerLayout_侧滑菜单控件---Android原生开发工作笔记120 2019-04-26
AndroidStudio安卓原生开发_UI高级_Shape的使用_虚线_直线_矩形_渐变_径向渐变_线性渐变_扫描渐变---Android原生开发工作笔记122 2019-04-26
AndroidStudio安卓原生开发_UI高级_StateListDrawable状态选择器_按钮按下和抬起显示不同颜色---Android原生开发工作笔记124 2019-04-26
kivy制作安卓APP--简单音乐播放器 2019-04-26
Angular2工程部署到Tomcat服务器,第一次访问正常,刷新浏览器后报404错误 2019-04-26
【力扣】155. 最小栈 2019-04-26
【力扣】160. 相交链表 2019-04-26
【力扣】167. 两数之和 II - 输入有序数组 2019-04-26
【力扣】168. Excel表列名称 2019-04-26
【力扣】456. 132 模式 2019-04-26
【力扣】82. 删除排序链表中的重复元素 II 2019-04-26
【剑指OFFER】 41. 数据流中的中位数 2019-04-26
【力扣】83. 删除排序链表中的重复元素 2019-04-26
【剑指OFFER】 43. 1~n 整数中 1 出现的次数 2019-04-26
【剑指OFFER】44. 数字序列中某一位的数字 2019-04-26
【剑指OFFER】45. 把数组排成最小的数 2019-04-26
【区块链】使用JAV简易A模拟创建区块链及挖矿 2019-04-26
【力扣】74. 搜索二维矩阵 2019-04-26