C++ 基于多态的插件式开发

发布时间:2023年12月25日

C++ 一种可扩展的开发模式-插件式开发

对插件式开发的理解

插件式开发是为了可扩展,同时减少对系统内其他组件的认知负担,只需要遵循特定的协议,开发好当前这个插件即可。
例如一个系统中可能存在以下功能: System={编解码;配置读写;缓存;寻址}。随着功能的迭代,系统的功能越来越多,单个功能的实现方式也越来越多样,例如缓存可以使用memcache、redis,配置读写可能是json、yaml等格式。那个这个系统一个良好的结构图可能是:
示例系统

插件式开发的实现思路

  1. 每种功能都对应多种实现方法,那么每种功能都可以定义一个接口,具体的实现交由不同的子类去实现
  2. 为了实现不同实现方式的调度,需要将所有子类管理起来,通过插件名来进行调度执行,也就是需要一个工厂管理插件

具体实现

插件基类的定义

插件基类定义了所有插件需要上报的一些基础信息和插件类型。

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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。