C++ 基于多态的插件式开发
2023-12-22 12:17:35
C++ 一种可扩展的开发模式-插件式开发
对插件式开发的理解
插件式开发是为了可扩展,同时减少对系统内其他组件的认知负担,只需要遵循特定的协议,开发好当前这个插件即可。
例如一个系统中可能存在以下功能: System={编解码;配置读写;缓存;寻址}。随着功能的迭代,系统的功能越来越多,单个功能的实现方式也越来越多样,例如缓存可以使用memcache、redis,配置读写可能是json、yaml等格式。那个这个系统一个良好的结构图可能是:
插件式开发的实现思路
- 每种功能都对应多种实现方法,那么每种功能都可以定义一个接口,具体的实现交由不同的子类去实现
- 为了实现不同实现方式的调度,需要将所有子类管理起来,通过插件名来进行调度执行,也就是需要一个工厂管理插件
具体实现
插件基类的定义
插件基类定义了所有插件需要上报的一些基础信息和插件类型。
enum class PluginType {
kUnknown, // 未知类型
kCodec, // 编解码插件
kConfig, // 配置读写组件
kCache, // 缓存组件
kNaming, // 寻址组件
};
class Plugin {
public:
virtual std::string Name() = 0;
virtual std::string Version() = 0;
virtual PluginType Type() = 0;
};
缓存类插件定义
我们定义了一个缓存类插件,包含一些基础的读写接口,所有缓存插件必须实现这些功能
class CachePlugin : public Plugin {
public:
PluginType Type() override { return PluginType::kCache; }
// 对于缓存组件我们规定以下几个动作:
// Init:初始化
// Destry:回收资源
// Set:写缓存
// Get:读缓存
virtual bool Init(const std::string &path) = 0;
virtual void Destry() = 0;
virtual bool Set(const std::string &key, const std::string &val) = 0;
virtual bool Get(const std::string &key, std::string &val) = 0;
};
Redis缓存、memcache缓存类定义
子类按照父类接口去实现对应功能。
class Redis : public CachePlugin {
public:
std::string Name() override { return "RedisPlugin"; }
std::string Version() override { return "Redis5.0"; }
bool Init(const std::string &path) override {
// ...
return true;
}
void Destry() override {}
bool Set(const std::string &key, const std::string &val) override {
// ...
return true;
}
bool Get(const std::string &key, std::string &val) override {
// ...
return true;
}
};
工厂
工厂通过读取配置文件实例化具体的缓存对象,存储到plugins_中,同时提供Get方法,以插件名获取插件。在实际使用的时候,通过插件名获取到不同的缓存插件,执行不同的动作。
/*
cache:
- redis
name: redis_cache
address: xx
code: xx
- memcache
name:
*/
class CacheFactory {
public:
using CachePluginType = std::shared_ptr<CachePlugin>;
bool LoadAllPlugins(const std::string &config) {
// 读取配置信息,将不同配置的redis、memcache实例化后插入到map中
for(...){
CachePluginType plugin;
if(plugin->Init(path)){
plugins_.emplace(name, plugin);
}
}
}
CachePluginType Get(const std::string &name) const {
auto itr = plugins_.find(name);
return itr == plugins_.end() ? nullptr : plugins_.at(name);
}
private:
std::unordered_map<std::string, CachePluginType> plugins_;
};
总结
插件化开发,可以利用C++的多态实现,基类定义接口,子类定义具体的行为,工厂负责插件的管理。当然,向工厂中注册的行为也可以进一步写成宏,更方便使用。
文章来源:https://blog.csdn.net/XYY_CN/article/details/135120053
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!