找回密码
 立即注册
收起左侧

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

0
回复
4087
查看
[复制链接]
累计签到:41 天
连续签到:1 天
来源: 原创 2019-8-28 17:09:53 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

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

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


----------------------------------------------------------------------------------------------------------------------

引言
----------------------------------------------------------------
   在很多人共同开发一个软件项目时,大家会分别负责不同的模块开发,最后把这些模块拼接成一个完整的程序。很多情况下,这些模块之间需要共享一些配置数据。这时,可能有人首先想到了全局变量。全局变量的确也能达到目的,但是我们有一个更好的选择,就是采用设计模式中的单体模式。本节,我们为朋友们介绍一下单体模式实现全局配置的方法。

正文
----------------------------------------------------------------
   单体模式(Singleton),顾名思义,指的是只有一个实体。那么怎样做才能让配置只有一个实体呢?
    在本节示例代码中,我们的保存配置信息的类为CConfig。为了实现单体模式,我们需要把CConfig做一下改造:把构造函数、析构函数、拷贝构造函数声明为私有成员:
代码清单04-19-01
config.h
  1. class KS04_19_CONFIG_Export CConfig {
  2.     // ……   
  3. private:   
  4.     /**
  5.     * @brief  构造函数,定义为私有的目的是防止他人使用该类构造对象。
  6.     * @return 无
  7.     */
  8.         CConfig() { }
  9.     /**
  10. * @brief  拷贝构造函数,定义为私有的目的是防止编译器调用默认的拷贝构造
  11. *         函数隐式构造该类的对象。
  12.     * @return 无
  13.     */
  14.         CConfig(const CConfig&);
  15.     /**
  16.     * @brief  析构造函数,定义为私有的目的是防止他人用delete语句删除单体对象。
  17.     * @return 无
  18.     */
  19.         ~CConfig(){}   
  20. };
复制代码
代码清单04-19-01中:
在第3~8行,为了保证该类对象只有一个实体存在,我们将构造函数声明为私有的,目的是防止他人使用该类构造对象(如果将类的构造函数声明为私有,则new CConfig这种代码将会被编译器报错,因为编译器无法调用私有的构造函数来构造对象,只能调用public的构造函数)。
我们将析构函数声明为私有,目的是防止他人用delete语句删除我们构造的单体对象。
另外,我们将拷贝构造函数也声明为私有,目的是防止编译器调用默认的拷贝构造函数隐式构造该类的对象。
好了,把所有能够构造对象的入口封住之后,我们来创建自己的接口来构造单体对象,方法如下,为CConfig添加一个私有成员:
代码清单04-19-02
config.h
  1. class KS04_19_CONFIG_Export CConfig {
  2.    // ......
  3. public:
  4.     static CConfig& instance();
  5. private:
  6.    static CConfig s_config;            /// 配置对象实例
  7.    // .....
  8. };
复制代码
代码清单04-19-02中:
在第6行,定义了一个私有的static成员对象。朋友们看到了吗?这个私有成员的类型就是CConfig。请注意,此行代码并不能构造该s_config对象,我们需要单独对其进行构造:
代码清单04-19-03
config.cpp:
  1. CConfig CConfig::s_config;
  2. CCfonfig::CConfig(){
  3.     //......
  4. }
复制代码
代码清单04-19-03中:
第1行的代码表示构造该s_config对象。

回到代码清单04-19-02:
在第4行,提供一个static接口用来访问该静态对象。
该接口实现如下:
代码清单04-19-04
config.cpp
  1. CConfig& CConfig::instance() {         
  2.     return s_config;
  3. }
复制代码
代码清单04-19-04中:
该接口的实现比较简单,直接返回之前定义的static对象即可。

到此为止,单体类定义好了。那么该怎么使用单体类呢?其实很简单。方法就是使用static接口的调用语法,如下代码将得到该单体对象的引用:
  1. CConfig::instance()
复制代码
比如,在本节示例代码中,我们在dll中调用该单体对象的接口设置参数:
代码清单04-19-05
model.cpp

  1. bool CModel::initialize() {
  2.     CConfig::instance().setSelectRadius(3.f);
  3.     return true;
  4. }
复制代码
代码清单04-19-05中;
第2行,通过CConfig::instance()静态接口得到单体对象的引用,然后调用其setSelectRadius()接口。
然后,我们在exe中调用该单体对象的接口获取刚刚设置的参数:
代码清单04-19-06
mian.cpp

  1. int main(int argc, char * argv[]) {
  2.     CModel model;
  3.     model.initialize();
  4.     qreal r = CConfig::instance().getSelectRadius();
  5.     cout << "r = " << r << endl;
  6.         return 0;
  7. }
复制代码

结语
----------------------------------------------------------------
  在本节中,我们介绍了通过单体模式实现全局配置的方法。在设计单体类时,需要注意的是下面几点:
    1). 将构造函数、析构函数、拷贝构造函数声明为私有成员。拷贝构造函数可以只定义不实现。
    2). 为单体类添加一个static成员变量,类型为该单体类。在cpp中需要用以下语句进行定义:

  1. CConfig CConfig::m_config;
复制代码
    3). 为单体类添加一个static成员接口,比如instance(),该接口无参数,返回类型为类的引用或类指针,该接口内部返回static成员变量的引用或指针。
    4). 如果在静态接口instance()内部构造一个static对象并返回该对象的引用,那么建议使用全局锁保护该static对象。如果作为类的成员变量,则不需要用锁保护(如果是指针类型的成员变量,则需要用锁进行保护)。
    5). 该单体对象的使用方法是通过类的static接口instance():
  1. CConfig::instance()
复制代码
好了,朋友们可以练习一下编写自己的单体类啦。



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了