baizy77 发表于 2019-8-28 17:09:53

KS04-19 用单体模式实现全局配置

本帖最后由 baizy77 于 2019-8-30 14:55 编辑

该文章原创于Qter开源社区(www.qter.org)作者: 女儿叫老白转载请注明出处!---------------------------------------------------------------------------------------------------------------------

[*]【独家连载】《Qt入门与提高-GUI产品开发》目录
[*]网页版课程源码 提取码:1uy7
[*]免费版视频教程

----------------------------------------------------------------------------------------------------------------------
引言----------------------------------------------------------------   在很多人共同开发一个软件项目时,大家会分别负责不同的模块开发,最后把这些模块拼接成一个完整的程序。很多情况下,这些模块之间需要共享一些配置数据。这时,可能有人首先想到了全局变量。全局变量的确也能达到目的,但是我们有一个更好的选择,就是采用设计模式中的单体模式。本节,我们为朋友们介绍一下单体模式实现全局配置的方法。
正文----------------------------------------------------------------   单体模式(Singleton),顾名思义,指的是只有一个实体。那么怎样做才能让配置只有一个实体呢?    在本节示例代码中,我们的保存配置信息的类为CConfig。为了实现单体模式,我们需要把CConfig做一下改造:把构造函数、析构函数、拷贝构造函数声明为私有成员:代码清单04-19-01config.hclass KS04_19_CONFIG_Export CConfig {
    // ……   
private:   
    /**
    * @brief构造函数,定义为私有的目的是防止他人使用该类构造对象。
    * @return 无
    */
      CConfig() { }
    /**
* @brief拷贝构造函数,定义为私有的目的是防止编译器调用默认的拷贝构造
*         函数隐式构造该类的对象。
    * @return 无
    */
      CConfig(const CConfig&);
    /**
    * @brief析构造函数,定义为私有的目的是防止他人用delete语句删除单体对象。
    * @return 无
    */
      ~CConfig(){}   
};
代码清单04-19-01中:在第3~8行,为了保证该类对象只有一个实体存在,我们将构造函数声明为私有的,目的是防止他人使用该类构造对象(如果将类的构造函数声明为私有,则new CConfig这种代码将会被编译器报错,因为编译器无法调用私有的构造函数来构造对象,只能调用public的构造函数)。我们将析构函数声明为私有,目的是防止他人用delete语句删除我们构造的单体对象。另外,我们将拷贝构造函数也声明为私有,目的是防止编译器调用默认的拷贝构造函数隐式构造该类的对象。好了,把所有能够构造对象的入口封住之后,我们来创建自己的接口来构造单体对象,方法如下,为CConfig添加一个私有成员:代码清单04-19-02config.hclass KS04_19_CONFIG_Export CConfig {
   // ......
public:
    static CConfig& instance();
private:
   static CConfig s_config;            /// 配置对象实例
   // .....
};
代码清单04-19-02中:在第6行,定义了一个私有的static成员对象。朋友们看到了吗?这个私有成员的类型就是CConfig。请注意,此行代码并不能构造该s_config对象,我们需要单独对其进行构造:代码清单04-19-03config.cpp:CConfig CConfig::s_config;
CCfonfig::CConfig(){
    //......
}
代码清单04-19-03中:第1行的代码表示构造该s_config对象。
回到代码清单04-19-02:在第4行,提供一个static接口用来访问该静态对象。该接口实现如下:代码清单04-19-04config.cppCConfig& CConfig::instance() {         
    return s_config;
}
代码清单04-19-04中:该接口的实现比较简单,直接返回之前定义的static对象即可。
到此为止,单体类定义好了。那么该怎么使用单体类呢?其实很简单。方法就是使用static接口的调用语法,如下代码将得到该单体对象的引用:CConfig::instance()比如,在本节示例代码中,我们在dll中调用该单体对象的接口设置参数:代码清单04-19-05model.cpp
bool CModel::initialize() {
    CConfig::instance().setSelectRadius(3.f);
    return true;
}
代码清单04-19-05中;第2行,通过CConfig::instance()静态接口得到单体对象的引用,然后调用其setSelectRadius()接口。然后,我们在exe中调用该单体对象的接口获取刚刚设置的参数:代码清单04-19-06mian.cpp
int main(int argc, char * argv[]) {
    CModel model;
    model.initialize();
    qreal r = CConfig::instance().getSelectRadius();
    cout << "r = " << r << endl;
      return 0;
}

结语----------------------------------------------------------------在本节中,我们介绍了通过单体模式实现全局配置的方法。在设计单体类时,需要注意的是下面几点:    1). 将构造函数、析构函数、拷贝构造函数声明为私有成员。拷贝构造函数可以只定义不实现。    2). 为单体类添加一个static成员变量,类型为该单体类。在cpp中需要用以下语句进行定义:
CConfig CConfig::m_config;    3). 为单体类添加一个static成员接口,比如instance(),该接口无参数,返回类型为类的引用或类指针,该接口内部返回static成员变量的引用或指针。    4). 如果在静态接口instance()内部构造一个static对象并返回该对象的引用,那么建议使用全局锁保护该static对象。如果作为类的成员变量,则不需要用锁保护(如果是指针类型的成员变量,则需要用锁进行保护)。    5). 该单体对象的使用方法是通过类的static接口instance():CConfig::instance()好了,朋友们可以练习一下编写自己的单体类啦。

课程目录: 《Qt入门与提高-GUI产品开发》目录
上一节:KS04-18 类的二进制格式序列化-向前兼容下一节:KS04-20   用流方式读写XML

页: [1]
查看完整版本: KS04-19 用单体模式实现全局配置