高性能分布式网络服务器--配置模块

配置模块

一般而言一个配置模块应该具备以下几点基本功能

  • 支持定义/声明配置项
  • 支持动态更新配置项的值
  • 支持从指定路径加载配置项
  • 支持给配置项注册配置变更通知
  • 支持给配置项设置校验方法
  • 支持导出当前配置

GitHub

  • https://github.com/huxiaohei/tiger.git

设计

tiger框架中的配置模块采用约定优于配置的设计思想

约定优于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。
本质是说,开发人员仅需规定应用中不符约定的部分。例如,如果模型中有个名为Sale的类,那么数据库中对应的表就会默认命名为sales。只有在偏离这一约定时,例如将该表命名为"products_sold",才需写有关这个名字的配置。如果所用工具的约定与期待相符,便可省去配置;反之,可以配置来达到所期待的方式。 ---- 维基百科

tiger的配置模块使用了yaml-cpp作为YAML解析库,关于yaml-cpp的编译以及使用方法可以点击这里关于YAML格式介绍可以点击这里

实现

配置模块中主要包括ConfValBaseConfigVarConfig三个类,以及用于各种类型转换的LexicalCast模版类

ConfValBase

为配置项值的虚基类,定义了配置项公有的成员和方法。

  • 配置项名称和配置项描述
  • 将配置项值序列化为string和将string反序列化为配置项对应的值

ConfigVar

ConfigVar为继承ConfValBase类的一个模版类,具备一个模版参数T,即配置项值类型

  • 在调用from_string方法时会实例化一个对应的LexicalCast<std::string, T>对象并执行对应的operator方法,将string反序列化为T类型的值
  • 在调用to_string方式时则会实例化一个对应的LexicalCast<T, std::string>对象并执行对应的operator方法,将T类型的值序列化为string

Config

ConfigConfigVar管理类,采用单例设计模式负责管理所有的ConfigVar对象

  • 提供Lookup方法用于查询配置,如果在查询时没有查到对应的值,则会新建一个配置项,并使用查询时的默认值参数。因此也保证了配置项定义即可用的特性。
  • 提供LoadFromYmal方法用于加载YAML配置文件,加载配置文件的同时也会更新已经存在的配置项

LexicalCast

LexicalCast为一个模版类template <typename FromType, typename ToType>,因其重载()运算符,其也是一个仿函数。根据FromTypeToType的不同,LexicalCast具有多种偏特化实现,而每一种偏特化实现都是将FromType类型转换为ToType类型

  • 基本类型转换

    template <typename FromType, typename ToType>
    class LexicalCast {
       public:
        ToType operator()(const FromType &v) {
            return boost::lexical_cast<ToType>(v);
        }
    };
    

    这里的LexicalCast类是一个仿函数,它支持LexicalCast<FromType, ToType>()(const FromType &v)调用,可将传入的FromType类型的参数v进行转换,并返回ToType类型的结果

  • vector类型转换

    template <typename T>
    class LexicalCast<std::string, std::vector<T>> {
       public:
        std::vector<T> operator()(const std::string &str) {
            YAML::Node root = YAML::Load(str);
            std::vector<T> v;
            std::stringstream ss;
            for (size_t i = 0; i < root.size(); ++i) {
                ss.str("");
                ss << root[i];
                v.push_back(LexicalCast<std::string, T>()(ss.str()));
            }
            return v;
        }
    };
    
    template <typename T>
    class LexicalCast<std::vector<T>, std::string> {
       public:
        std::string operator()(const std::vector<T> &v) {
            YAML::Node node;
            for (const auto &it : v) {
                node.push_back(LexicalCast<T, std::string>()(it));
            }
            std::stringstream ss;
            ss << node;
            return ss.str();
        }
    };
    

    可见在将stringstd::vector<T>类型相互转换的时,如果T不是基本类型,那么将会继续实例化特定模版,直到T为基础类型

  • 其余类型转换
    其余类型转换与vector类型转换原理一致,详细请参考源码

每添加一个新类型的转换,那这个类型和之前已实现的类型组合出的数据类型也可以顺利转换。比如新加map类型转换,那么就可以组合出 vector<map>map<vector>map<map>等。这种基于偏特化实现类型转换方法,可将代码做到高度简化,但功能却非常强大,并且后续维护和扩展非常方便。这也展示了泛型程序设计的强大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虎小黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值